filecompare.c 13 KB

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