cell_stats.c 7.5 KB

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