cell_stats.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. #include <grass/gis.h>
  2. #include <stdlib.h>
  3. #define INCR 10
  4. #define SHIFT 6
  5. static int NCATS = 1 << SHIFT;
  6. #define NODE struct Cell_stats_node
  7. static int next_node(struct Cell_stats *);
  8. static int init_node(NODE *, int, int);
  9. /*!
  10. * \brief initialize cell stats
  11. *
  12. * This routine, which must be called first, initializes the Cell_stats
  13. * structure <b>s.</b>
  14. *
  15. * \param s
  16. * \return int
  17. */
  18. /*!
  19. * \brief
  20. *
  21. * Set the count for NULL-values to zero.
  22. *
  23. * \return int
  24. */
  25. int G_init_cell_stats(struct Cell_stats *s)
  26. {
  27. s->N = 0;
  28. s->tlen = INCR;
  29. s->node = (NODE *) G_malloc(s->tlen * sizeof(NODE));
  30. s->null_data_count = 0;
  31. return 1;
  32. }
  33. /*!
  34. * \brief add data to cell stats
  35. *
  36. * The <b>n</b> CELL values in the <b>data</b>
  37. * array are inserted (and counted) in the Cell_stats structure <b>s.</b>
  38. *
  39. * \param data
  40. * \param n
  41. * \param s
  42. * \return int
  43. */
  44. /*!
  45. * \brief
  46. *
  47. * Look for NULLs and update the
  48. * NULL-value count.
  49. *
  50. * \return int
  51. */
  52. int G_update_cell_stats(const CELL * cell, int n, struct Cell_stats *s)
  53. {
  54. CELL cat;
  55. register int p, q;
  56. int idx, offset;
  57. int N;
  58. register NODE *node, *pnode;
  59. register NODE *new_node;
  60. if (n <= 0)
  61. return 1;
  62. node = s->node;
  63. /* first non-null node is special case */
  64. if ((N = s->N) == 0) {
  65. cat = *cell++;
  66. while (G_is_c_null_value(&cat)) {
  67. s->null_data_count++;
  68. cat = *cell++;
  69. n--;
  70. }
  71. if (n > 0) { /* if there are some non-null cells */
  72. N = 1;
  73. if (cat < 0) {
  74. idx = -((-cat) >> SHIFT) - 1;
  75. offset = cat + ((-idx) << SHIFT) - 1;
  76. }
  77. else {
  78. idx = cat >> SHIFT;
  79. offset = cat - (idx << SHIFT);
  80. }
  81. fflush(stderr);
  82. init_node(&node[1], idx, offset);
  83. node[1].right = 0;
  84. n--;
  85. }
  86. }
  87. while (n-- > 0) {
  88. cat = *cell++;
  89. if (G_is_c_null_value(&cat)) {
  90. s->null_data_count++;
  91. continue;
  92. }
  93. if (cat < 0) {
  94. idx = -((-cat) >> SHIFT) - 1;
  95. offset = cat + ((-idx) << SHIFT) - 1;
  96. }
  97. else {
  98. idx = cat >> SHIFT;
  99. offset = cat - (idx << SHIFT);
  100. }
  101. q = 1;
  102. while (q > 0) {
  103. pnode = &node[p = q];
  104. if (pnode->idx == idx) {
  105. pnode->count[offset]++;
  106. break;
  107. }
  108. if (pnode->idx > idx)
  109. q = pnode->left; /* go left */
  110. else
  111. q = pnode->right; /* go right */
  112. }
  113. if (q > 0)
  114. continue; /* found */
  115. /* new node */
  116. N++;
  117. /* grow the tree? */
  118. if (N >= s->tlen) {
  119. node =
  120. (NODE *) G_realloc((char *)node,
  121. sizeof(NODE) * (s->tlen += INCR));
  122. pnode = &node[p]; /* realloc moves node, must reassign pnode */
  123. }
  124. /* add node to tree */
  125. init_node(new_node = &node[N], idx, offset);
  126. if (pnode->idx > idx) {
  127. new_node->right = -p; /* create thread */
  128. pnode->left = N; /* insert left */
  129. }
  130. else {
  131. new_node->right = pnode->right; /* copy right link/thread */
  132. pnode->right = N; /* add right */
  133. }
  134. } /* while n-- > 0 */
  135. s->N = N;
  136. s->node = node;
  137. return 0;
  138. }
  139. static int init_node(NODE * node, int idx, int offset)
  140. {
  141. register long *count;
  142. register int i;
  143. count = node->count = (long *)G_calloc(i = NCATS, sizeof(long));
  144. while (i--)
  145. *count++ = 0;
  146. node->idx = idx;
  147. node->count[offset] = 1;
  148. node->left = 0;
  149. return 0;
  150. }
  151. /*!
  152. * \brief random query of cell stats
  153. *
  154. * This routine allows a random query of the
  155. * Cell_stats structure <b>s.</b> The <b>count</b> associated with the
  156. * raster value <b>cat</b> is set. The routine returns 1 if <b>cat</b> was
  157. * found in the structure, 0 otherwise.
  158. *
  159. * \param cat
  160. * \param count
  161. * \param s
  162. * \return int
  163. */
  164. /*!
  165. * \brief
  166. *
  167. * Allow finding the count for the
  168. * NULL-value
  169. *
  170. * \return int
  171. */
  172. int G_find_cell_stat(CELL cat, long *count, const struct Cell_stats *s)
  173. {
  174. register int q;
  175. register int idx;
  176. int offset;
  177. *count = 0;
  178. if (G_is_c_null_value(&cat)) {
  179. *count = s->null_data_count;
  180. return (*count != 0);
  181. }
  182. if (s->N <= 0)
  183. return 0;
  184. /*
  185. if (cat < 0)
  186. {
  187. idx = -(-cat/NCATS) - 1;
  188. offset = cat - idx*NCATS - 1;
  189. }
  190. else
  191. {
  192. idx = cat/NCATS;
  193. offset = cat - idx*NCATS;
  194. }
  195. */
  196. if (cat < 0) {
  197. idx = -((-cat) >> SHIFT) - 1;
  198. offset = cat + ((-idx) << SHIFT) - 1;
  199. }
  200. else {
  201. idx = cat >> SHIFT;
  202. offset = cat - (idx << SHIFT);
  203. }
  204. q = 1;
  205. while (q > 0) {
  206. if (s->node[q].idx == idx) {
  207. *count = s->node[q].count[offset];
  208. return (*count != 0);
  209. }
  210. if (s->node[q].idx > idx)
  211. q = s->node[q].left; /* go left */
  212. else
  213. q = s->node[q].right; /* go right */
  214. }
  215. return 0;
  216. }
  217. /*!
  218. * \brief reset/rewind cell stats
  219. *
  220. * The structure <b>s</b> is rewound (i.e., positioned at the first
  221. * raster category) so that sorted sequential retrieval can begin.
  222. *
  223. * \param s
  224. * \return int
  225. */
  226. int G_rewind_cell_stats(struct Cell_stats *s)
  227. {
  228. int q;
  229. if (s->N <= 0)
  230. return 1;
  231. /* start at root and go all the way to the left */
  232. s->curp = 1;
  233. while ((q = s->node[s->curp].left))
  234. s->curp = q;
  235. s->curoffset = -1;
  236. return 0;
  237. }
  238. static int next_node(struct Cell_stats *s)
  239. {
  240. int q;
  241. /* go to the right */
  242. s->curp = s->node[s->curp].right;
  243. if (s->curp == 0) /* no more */
  244. return 0;
  245. if (s->curp < 0) { /* thread. stop here */
  246. s->curp = -(s->curp);
  247. return 1;
  248. }
  249. while ((q = s->node[s->curp].left)) /* now go all the way left */
  250. s->curp = q;
  251. return 1;
  252. }
  253. /*!
  254. * \brief retrieve sorted cell stats
  255. *
  256. * Retrieves the next <b>cat,count</b>
  257. * combination from the structure <b>s.</b> Returns 0 if there are no more
  258. * items, non-zero if there are more.
  259. * For example:
  260. *
  261. \code
  262. struct Cell_stats s;
  263. CELL cat;
  264. long count;
  265. // updating <b>s</b> occurs here
  266. G_rewind_cell_stats(&s);
  267. while (G_next_cell_stat(&cat,&count,&s)
  268. fprintf(stdout, "%ld %ld\n", (long) cat, count);
  269. \endcode
  270. *
  271. * \param cat
  272. * \param count
  273. * \param s
  274. * \return int
  275. */
  276. /*!
  277. * \brief
  278. *
  279. * Do not return a record for the
  280. * NULL-value
  281. *
  282. * \return int
  283. */
  284. int G_next_cell_stat(CELL * cat, long *count, struct Cell_stats *s)
  285. {
  286. int idx;
  287. /* first time report stats for null */
  288. /* decided not to return stats for null in this function
  289. static int null_reported = 0;
  290. if(!null_reported && s->null_data_count > 0)
  291. {
  292. *count = s->null_data_count;
  293. G_set_c_null_value(&cat,1);
  294. null_reported = 1;
  295. return 1;
  296. }
  297. */
  298. if (s->N <= 0)
  299. return 0;
  300. for (;;) {
  301. s->curoffset++;
  302. if (s->curoffset >= NCATS) {
  303. if (!next_node(s))
  304. return 0;
  305. s->curoffset = -1;
  306. continue;
  307. }
  308. if ((*count = s->node[s->curp].count[s->curoffset])) {
  309. idx = s->node[s->curp].idx;
  310. /*
  311. if (idx < 0)
  312. *cat = idx*NCATS + s->curoffset+1;
  313. else
  314. *cat = idx*NCATS + s->curoffset;
  315. */
  316. if (idx < 0)
  317. *cat = -((-idx) << SHIFT) + s->curoffset + 1;
  318. else
  319. *cat = (idx << SHIFT) + s->curoffset;
  320. return 1;
  321. }
  322. }
  323. }
  324. /*!
  325. * \brief
  326. *
  327. * Get a number of null values from stats structure. Note: when reporting
  328. * values which appear in a map using G_next_cell_stats(), to get stats for
  329. * null, call G_get_stats_for_null_value() first, since
  330. * G_next_cell_stats() does not report stats for null.
  331. *
  332. * \param count
  333. * \param s
  334. * \return int
  335. */
  336. int G_get_stats_for_null_value(long *count, const struct Cell_stats *s)
  337. {
  338. *count = s->null_data_count;
  339. return 1;
  340. }
  341. /*!
  342. * \brief free cell stats
  343. *
  344. * The memory associated with structure <b>s</b> is freed. This routine may be
  345. * called any time after calling<i>G_init_cell_stats.</i>
  346. *
  347. * \param s
  348. * \return int
  349. */
  350. int G_free_cell_stats(struct Cell_stats *s)
  351. {
  352. int i;
  353. for (i = 1; i <= s->N; i++)
  354. G_free(s->node[i].count);
  355. G_free(s->node);
  356. return 0;
  357. }