filecompare.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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. static unsigned char clearMask[9] =
  10. { 255, 128, 192, 224, 240, 248, 252, 254, 255 };
  11. /*---------------------------------------------------------------------------*/
  12. static void G3d_float2xdrFloat(float *f, float *xdrf)
  13. {
  14. XDR xdrEncodeStream;
  15. xdrmem_create(&xdrEncodeStream, (caddr_t) xdrf, 4, XDR_ENCODE);
  16. if (!xdr_setpos(&xdrEncodeStream, 0))
  17. G3d_fatalError("G3d_float2xdrFloat: positioning xdr failed");
  18. if (!xdr_float(&xdrEncodeStream, f))
  19. G3d_fatalError("G3d_float2xdrFloat: writing xdr failed");
  20. xdr_destroy(&xdrEncodeStream);
  21. }
  22. /*---------------------------------------------------------------------------*/
  23. static void G3d_double2xdrDouble(double *d, double *xdrd)
  24. {
  25. XDR xdrEncodeStream;
  26. xdrmem_create(&xdrEncodeStream, (caddr_t) xdrd, 8, XDR_ENCODE);
  27. if (!xdr_setpos(&xdrEncodeStream, 0))
  28. G3d_fatalError("G3d_double2xdrDouble: positioning xdr failed");
  29. if (!xdr_double(&xdrEncodeStream, d))
  30. G3d_fatalError("G3d_double2xdrDouble: writing xdr failed");
  31. xdr_destroy(&xdrEncodeStream);
  32. }
  33. /*---------------------------------------------------------------------------*/
  34. static void G3d_truncFloat(float *f, int p)
  35. {
  36. unsigned char *c;
  37. if ((p == -1) || (p >= 23))
  38. return;
  39. c = (unsigned char *)f;
  40. c++;
  41. if (p <= 7) {
  42. *c++ &= clearMask[(p + 1) % 8];
  43. *c++ = 0;
  44. *c = 0;
  45. return;
  46. }
  47. c++;
  48. if (p <= 15) {
  49. *c++ &= clearMask[(p + 1) % 8];
  50. *c = 0;
  51. return;
  52. }
  53. c++;
  54. *c &= clearMask[(p + 1) % 8];
  55. return;
  56. }
  57. /*---------------------------------------------------------------------------*/
  58. static void G3d_truncDouble(double *d, int p)
  59. {
  60. unsigned char *c;
  61. if ((p == -1) || (p >= 52))
  62. return;
  63. c = (unsigned char *)d;
  64. c++;
  65. if (p <= 4) {
  66. *c++ &= clearMask[(p + 4) % 8];
  67. *c++ = 0;
  68. *c++ = 0;
  69. *c++ = 0;
  70. *c++ = 0;
  71. *c++ = 0;
  72. *c = 0;
  73. return;
  74. }
  75. c++;
  76. if (p <= 12) {
  77. *c++ &= clearMask[(p + 4) % 8];
  78. *c++ = 0;
  79. *c++ = 0;
  80. *c++ = 0;
  81. *c++ = 0;
  82. *c = 0;
  83. return;
  84. }
  85. c++;
  86. if (p <= 20) {
  87. *c++ &= clearMask[(p + 4) % 8];
  88. *c++ = 0;
  89. *c++ = 0;
  90. *c++ = 0;
  91. *c = 0;
  92. return;
  93. }
  94. c++;
  95. if (p <= 28) {
  96. *c++ &= clearMask[(p + 4) % 8];
  97. *c++ = 0;
  98. *c++ = 0;
  99. *c = 0;
  100. return;
  101. }
  102. c++;
  103. if (p <= 36) {
  104. *c++ &= clearMask[(p + 4) % 8];
  105. *c++ = 0;
  106. *c = 0;
  107. return;
  108. }
  109. c++;
  110. if (p <= 44) {
  111. *c++ &= clearMask[(p + 4) % 8];
  112. *c = 0;
  113. return;
  114. }
  115. c++;
  116. *c &= clearMask[(p + 4) % 8];
  117. return;
  118. }
  119. /*---------------------------------------------------------------------------*/
  120. static void G3d_float2Double(float *f, double *d)
  121. {
  122. unsigned char *c1, *c2, sign, c;
  123. int e;
  124. c1 = (unsigned char *)f;
  125. c2 = (unsigned char *)d;
  126. sign = (*c1 & (unsigned char)128);
  127. e = (((*c1 & (unsigned char)127) << 1) |
  128. ((*(c1 + 1) & (unsigned char)128) >> 7));
  129. if ((*c1 != 0) || (*(c1 + 1) != 0) || (*(c1 + 2) != 0) ||
  130. (*(c1 + 3) != 0))
  131. e += 1023 - 127;
  132. c = e / 16;
  133. *c2++ = (sign | c);
  134. c1++;
  135. c = e % 16;
  136. *c2 = (c << 4);
  137. *c2++ |= ((*c1 & (unsigned char)127) >> 3);
  138. *c2 = ((*c1++ & (unsigned char)7) << 5);
  139. *c2++ |= (*c1 >> 3);
  140. *c2 = ((*c1++ & (unsigned char)7) << 5);
  141. *c2++ |= (*c1 >> 3);
  142. *c2++ = ((*c1 & (unsigned char)7) << 5);
  143. *c2++ = (unsigned char)0;
  144. *c2++ = (unsigned char)0;
  145. *c2 = (unsigned char)0;
  146. }
  147. /*---------------------------------------------------------------------------*/
  148. static int G3d_compareFloats(float *f1, int p1, float *f2, int p2)
  149. {
  150. unsigned char *c1, *c2;
  151. float xdrf1, xdrf2;
  152. if (G3d_isNullValueNum(f1, FCELL_TYPE))
  153. return G3d_isNullValueNum(f2, FCELL_TYPE);
  154. G3d_float2xdrFloat(f1, &xdrf1);
  155. G3d_float2xdrFloat(f2, &xdrf2);
  156. c1 = (unsigned char *)&xdrf1;
  157. c2 = (unsigned char *)&xdrf2;
  158. /* 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); */
  159. if ((p1 != -1) && (p1 < 23) && ((p1 < p2) || (p2 == -1)))
  160. G3d_truncFloat(&xdrf2, p1);
  161. if ((p2 != -1) && (p2 < 23) && ((p2 < p1) || (p1 == -1)))
  162. G3d_truncFloat(&xdrf1, p2);
  163. /* 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); */
  164. return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
  165. (*(c1 + 2) == *(c2 + 2))
  166. && (*(c1 + 3) == *(c2 + 3));
  167. }
  168. /*---------------------------------------------------------------------------*/
  169. static int G3d_compareDoubles(double *d1, int p1, double *d2, int p2)
  170. {
  171. unsigned char *c1, *c2;
  172. double xdrd1, xdrd2;
  173. if (G3d_isNullValueNum(d1, DCELL_TYPE))
  174. return G3d_isNullValueNum(d2, DCELL_TYPE);
  175. G3d_double2xdrDouble(d1, &xdrd1);
  176. G3d_double2xdrDouble(d2, &xdrd2);
  177. c1 = (unsigned char *)&xdrd1;
  178. c2 = (unsigned char *)&xdrd2;
  179. /* 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)); */
  180. if ((p1 != -1) && (p1 < 52) && ((p1 < p2) || (p2 == -1)))
  181. G3d_truncDouble(&xdrd2, p1);
  182. if ((p2 != -1) && (p2 < 52) && ((p2 < p1) || (p1 == -1)))
  183. G3d_truncDouble(&xdrd1, p2);
  184. /* 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)); */
  185. return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
  186. (*(c1 + 2) == *(c2 + 2))
  187. && (*(c1 + 3) == *(c2 + 3)) && (*(c1 + 4) == *(c2 + 4))
  188. && (*(c1 + 5) == *(c2 + 5)) && (*(c1 + 6) == *(c2 + 6))
  189. && (*(c1 + 7) == *(c2 + 7));
  190. }
  191. /*---------------------------------------------------------------------------*/
  192. static int G3d_compareFloatDouble(float *f, int p1, double *d, int p2)
  193. {
  194. unsigned char *c1, *c2;
  195. float xdrf, fTmp;
  196. double xdrd, xdrd2, dTmp;
  197. if (G3d_isNullValueNum(f, FCELL_TYPE))
  198. return G3d_isNullValueNum(d, DCELL_TYPE);
  199. /* need this since assigning a double to a float actually may change the */
  200. /* bit pattern. an example (in xdr format) is the double */
  201. /* (63 237 133 81 81 108 3 32) which truncated to 23 bits precision should */
  202. /* become (63 237 133 81 64 0 0 0). however assigned to a float it becomes */
  203. /* (63 237 133 81 96 0 0 0). */
  204. fTmp = *d;
  205. dTmp = fTmp;
  206. G3d_float2xdrFloat(f, &xdrf);
  207. G3d_float2Double(&xdrf, &xdrd2);
  208. G3d_double2xdrDouble(&dTmp, &xdrd);
  209. c1 = (unsigned char *)&xdrd2;
  210. c2 = (unsigned char *)&xdrd;
  211. /* 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)); */
  212. if (((p1 != -1) && ((p1 < p2) || (p2 == -1))) ||
  213. ((p1 == -1) && ((p2 > 23) || (p2 == -1))))
  214. G3d_truncDouble(&xdrd, (p1 != -1 ? p1 : 23));
  215. if ((p2 != -1) && (p2 < 23) && ((p2 < p1) || (p1 == -1)))
  216. G3d_truncDouble(&xdrd2, p2);
  217. /* 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)); */
  218. return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
  219. (*(c1 + 2) == *(c2 + 2))
  220. && (*(c1 + 3) == *(c2 + 3)) && (*(c1 + 4) == *(c2 + 4))
  221. && (*(c1 + 5) == *(c2 + 5)) && (*(c1 + 6) == *(c2 + 6))
  222. && (*(c1 + 7) == *(c2 + 7));
  223. }
  224. /*---------------------------------------------------------------------------*/
  225. static void compareFilesNocache(void *map, void *map2)
  226. {
  227. double n1 = 0, n2 = 0;
  228. double *n1p, *n2p;
  229. float *f1p, *f2p;
  230. int x, y, z, correct;
  231. int p1, p2;
  232. int tileX, tileY, tileZ, typeIntern, typeIntern2;
  233. int nx, ny, nz;
  234. p1 = G3d_tilePrecisionMap(map);
  235. p2 = G3d_tilePrecisionMap(map2);
  236. G3d_getTileDimensionsMap(map, &tileX, &tileY, &tileZ);
  237. G3d_getNofTilesMap(map2, &nx, &ny, &nz);
  238. typeIntern = G3d_tileTypeMap(map);
  239. typeIntern2 = G3d_tileTypeMap(map2);
  240. n1p = &n1;
  241. f1p = (float *)&n1;
  242. n2p = &n2;
  243. f2p = (float *)&n2;
  244. for (z = 0; z < nz * tileZ; z++) {
  245. printf("comparing: z = %d\n", z);
  246. for (y = 0; y < ny * tileY; y++) {
  247. for (x = 0; x < nx * tileX; x++) {
  248. G3d_getBlock(map, x, y, z, 1, 1, 1, n1p, typeIntern);
  249. G3d_getBlock(map2, x, y, z, 1, 1, 1, n2p, typeIntern2);
  250. if (typeIntern == FCELL_TYPE) {
  251. if (typeIntern2 == FCELL_TYPE)
  252. correct = G3d_compareFloats(f1p, p1, f2p, p2);
  253. else
  254. correct = G3d_compareFloatDouble(f1p, p1, n2p, p2);
  255. }
  256. else {
  257. if (typeIntern2 == FCELL_TYPE)
  258. correct = G3d_compareFloatDouble(f2p, p2, n1p, p1);
  259. else
  260. correct = G3d_compareDoubles(n1p, p1, n2p, p2);
  261. }
  262. if (!correct) {
  263. int xTile, yTile, zTile, xOffs, yOffs, zOffs;
  264. G3d_coord2tileCoord(map2, x, y, z, &xTile, &yTile, &zTile,
  265. &xOffs, &yOffs, &zOffs);
  266. printf("(%d %d %d) (%d %d %d) (%d %d %d) %.20f %.20f\n",
  267. x, y, z, xTile, yTile, zTile, xOffs, yOffs, zOffs,
  268. *n1p, *n2p);
  269. G3d_fatalError
  270. ("compareFilesNocache: files don't match\n");
  271. }
  272. }
  273. }
  274. }
  275. printf("Files are identical up to precision.\n");
  276. }
  277. /*---------------------------------------------------------------------------*/
  278. /*!
  279. * \brief
  280. *
  281. * Compares the cell-values of file <em>f1</em> in mapset
  282. * <em>mapset1</em> and file <em>f2</em> in mapset <em>mapset2</em>.
  283. * The values are compared up to precision.
  284. * Terminates in error if the files don't match.
  285. * This function uses the more advanced features of the cache.
  286. * The source code can be found in <em>filecompare.c</em>.
  287. *
  288. * \param f1
  289. * \param mapset1
  290. * \param f2
  291. * \param mapset2
  292. * \return void
  293. */
  294. void
  295. G3d_compareFiles(const char *f1, const char *mapset1, const char *f2,
  296. const char *mapset2)
  297. {
  298. void *map, *map2;
  299. double n1 = 0, n2 = 0;
  300. double *n1p, *n2p;
  301. float *f1p, *f2p;
  302. int x, y, z, correct;
  303. int p1, p2;
  304. int rows, cols, depths;
  305. int tileX, tileY, tileZ, typeIntern, typeIntern2, tileX2, tileY2, tileZ2;
  306. int nx, ny, nz;
  307. printf("\nComparing %s and %s\n", f1, f2);
  308. map = G3d_openCellOld(f1, mapset1, G3D_DEFAULT_WINDOW,
  309. G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
  310. if (map == NULL)
  311. G3d_fatalError("G3d_compareFiles: error in G3d_openCellOld");
  312. G3d_printHeader(map);
  313. map2 = G3d_openCellOld(f2, mapset2, G3D_DEFAULT_WINDOW,
  314. G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
  315. if (map2 == NULL)
  316. G3d_fatalError("G3d_compareFiles: error in G3d_openCellOld");
  317. G3d_printHeader(map2);
  318. typeIntern = G3d_tileTypeMap(map);
  319. typeIntern2 = G3d_tileTypeMap(map2);
  320. p1 = G3d_tilePrecisionMap(map);
  321. p2 = G3d_tilePrecisionMap(map2);
  322. G3d_getTileDimensionsMap(map, &tileX, &tileY, &tileZ);
  323. G3d_getTileDimensionsMap(map2, &tileX2, &tileY2, &tileZ2);
  324. G3d_getNofTilesMap(map2, &nx, &ny, &nz);
  325. G3d_getCoordsMap(map, &rows, &cols, &depths);
  326. if ((!G3d_tileUseCacheMap(map)) || (!G3d_tileUseCacheMap(map2))) {
  327. compareFilesNocache(map, map2);
  328. G3d_closeCell(map);
  329. G3d_closeCell(map2);
  330. return;
  331. }
  332. n1p = &n1;
  333. f1p = (float *)&n1;
  334. n2p = &n2;
  335. f2p = (float *)&n2;
  336. G3d_autolockOn(map);
  337. G3d_autolockOn(map2);
  338. G3d_minUnlocked(map, cols / tileX + 1);
  339. G3d_getCoordsMap(map2, &rows, &cols, &depths);
  340. G3d_minUnlocked(map2, cols / tileX + 1);
  341. G3d_getCoordsMap(map, &rows, &cols, &depths);
  342. for (z = 0; z < depths; z++) {
  343. printf("comparing: z = %d\n", z);
  344. if ((z % tileZ) == 0) {
  345. if (!G3d_unlockAll(map))
  346. G3d_fatalError("G3d_compareFiles: error in G3d_unlockAll");
  347. }
  348. if ((z % tileZ2) == 0) {
  349. if (!G3d_unlockAll(map2))
  350. G3d_fatalError("G3d_compareFiles: error in G3d_unlockAll");
  351. }
  352. for (y = 0; y < rows; y++) {
  353. for (x = 0; x < cols; x++) {
  354. G3d_getValueRegion(map, x, y, z, n1p, typeIntern);
  355. G3d_getValueRegion(map2, x, y, z, n2p, typeIntern2);
  356. G3d_isNullValueNum(n1p, typeIntern);
  357. G3d_isNullValueNum(n2p, typeIntern2);
  358. if (typeIntern == FCELL_TYPE) {
  359. if (typeIntern2 == FCELL_TYPE)
  360. correct = G3d_compareFloats(f1p, p1, f2p, p2);
  361. else
  362. correct = G3d_compareFloatDouble(f1p, p1, n2p, p2);
  363. }
  364. else {
  365. if (typeIntern2 == FCELL_TYPE)
  366. correct = G3d_compareFloatDouble(f2p, p2, n1p, p1);
  367. else
  368. correct = G3d_compareDoubles(n1p, p1, n2p, p2);
  369. }
  370. if (!correct) {
  371. int xTile, yTile, zTile, xOffs, yOffs, zOffs;
  372. G3d_coord2tileCoord(map2, x, y, z, &xTile, &yTile, &zTile,
  373. &xOffs, &yOffs, &zOffs);
  374. G3d_fatalError("G3d_compareFiles: files don't match\n");
  375. }
  376. }
  377. }
  378. }
  379. printf("Files are identical up to precision.\n");
  380. G3d_closeCell(map);
  381. G3d_closeCell(map2);
  382. }