GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
sparse.c
Go to the documentation of this file.
1 /*
2  ** Bitmap library
3  **
4  ** Written by David Gerdes 12 November 1992
5  ** US Army Construction Engineering Research Laboratories
6  **
7  **
8  ** This library provides basic support for the creation and manipulation
9  ** of two dimensional bitmap arrays.
10  **
11  ** BM_create (x, y) Create bitmap of specified dimensions
12  **
13  ** BM_destroy (map) Destroy bitmap and free memory
14  **
15  ** BM_set (map, x, y, val) Set array position to val [TRUE/FALSE]
16  **
17  ** BM_get (map, x, y) Return value at array position
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <grass/linkm.h>
23 #include <grass/bitmap.h>
24 
25 #define BM_col_to_byte(x) ((x) >> 3) /* x / 8 */
26 #define BM_col_to_bit(x) ((x) & 7) /* x % 8 */
27 
28 static int depth;
29 
30 /*!
31  * \brief
32  *
33  * Create a sparse bitmap of dimension 'x'/'y'
34  *
35  * Returns bitmap structure or NULL on error
36  *
37  * \param x
38  * \param y
39  * \return struct BM
40  */
41 struct BM *BM_create_sparse(int x, int y)
42 {
43  struct BM *map;
44  int i;
45 
46  if (NULL == (map = (struct BM *)malloc(sizeof(struct BM))))
47  return (NULL);
48  map->bytes = (x + 7) / 8;
49 
50  if (NULL ==
51  (map->data = (unsigned char *)malloc(sizeof(struct BMlink *) * y))) {
52  free(map);
53  return (NULL);
54  }
55 
56  map->rows = y;
57  map->cols = x;
58  map->sparse = 1;
59 
61  map->token = link_init(sizeof(struct BMlink));
62 
63  for (i = 0; i < map->rows; i++) {
64  ((struct BMlink **)(map->data))[i] =
65  (struct BMlink *)link_new(map->token);
66  ((struct BMlink **)(map->data))[i]->count = x;
67  ((struct BMlink **)(map->data))[i]->val = 0;
68  ((struct BMlink **)(map->data))[i]->next = NULL;
69  }
70 
71  depth++;
72 
73  return map;
74 }
75 
76 /*!
77  * \brief
78  *
79  * Destroy sparse bitmap and free all associated memory
80  *
81  * Returns 0
82  *
83  * \param map
84  * \return int
85  */
86 int BM_destroy_sparse(struct BM *map)
87 {
88  int i;
89  struct BMlink *p, *tmp;
90 
91  for (i = 0; i < map->rows; i++) {
92  p = ((struct BMlink **)(map->data))[i];
93  while (p != NULL) {
94  tmp = p->next;
95  link_dispose(map->token, (VOID_T *)p);
96  p = tmp;
97  }
98  }
99 
100  if (--depth == 0)
101  link_cleanup(map->token);
102 
103  free(map->data);
104  free(map);
105 
106  return 0;
107 }
108 
109 /*!
110  * \brief
111  *
112  * Set sparse bitmap value to 'val' at location 'x'/'y'
113  *
114  * Returns 0
115  *
116  * \param map
117  * \param x
118  * \param y
119  * \param val
120  * \return int
121  */
122 int BM_set_sparse(struct BM *map, int x, int y, int val)
123 {
124  struct BMlink *p, *p2, *prev;
125  int cur_x = 0;
126  int Tval;
127  int dist_a, dist_b;
128 
129  val = !(!val); /* set val == 1 or 0 */
130 
131  p = ((struct BMlink **)(map->data))[y];
132  prev = NULL;
133  while (p != NULL) {
134  if (cur_x + p->count > x) {
135  if (p->val == val) /* no change */
136  return 0;
137 
138  Tval = p->val;
139 
140  /* if x is on edge, then we probably want to merge it with
141  ** its neighbor for efficiency
142  */
143 
144  /* dist_a is how far x is from Left edge of group */
145  /* dist_b is how far x is from right edge of group */
146 
147  dist_a = x - cur_x;
148  dist_b = (cur_x + p->count - 1) - x;
149 
150  /* if on both edges, then we should be able to merge 3 into one */
151  if (dist_b == 0 && p->next && p->next->val == val) {
152  if (dist_a == 0 && x > 0) {
153  if (prev != NULL && prev->val == val) {
154  prev->count += p->next->count + 1;
155  prev->next = p->next->next;
156  link_dispose(map->token, (VOID_T *)p->next);
157  link_dispose(map->token, (VOID_T *)p);
158  return 0;
159  }
160  }
161  }
162 
163  /* handle right edge merge */
164  if (dist_b == 0 && p->next && p->next->val == val) {
165  p->count--;
166  p->next->count++;
167  if (p->count == 0) {
168  if (prev) {
169  prev->next = p->next;
170  }
171  else {
172  ((struct BMlink **)(map->data))[y] = p->next;
173  }
174  link_dispose(map->token, (VOID_T *)p);
175  }
176  return 0;
177  }
178 
179  /* handle left edge merge */
180  if (dist_a == 0 && x > 0) {
181 
182  if (prev != NULL && prev->val == val) {
183  prev->count++;
184  p->count--;
185  if (p->count == 0) {
186  prev->next = p->next;
187  link_dispose(map->token, (VOID_T *)p);
188  }
189  return 0;
190  }
191  }
192 
193  /* if not on edge, have to add link for each side */
194  if (dist_a > 0) {
195  p->count = dist_a;
196  p->val = Tval;
197  p2 = (struct BMlink *)link_new(map->token);
198  p2->next = p->next;
199  p->next = p2;
200  p = p2;
201  }
202  p->count = 1;
203  p->val = val;
204 
205  if (dist_b > 0) {
206  p2 = (struct BMlink *)link_new(map->token);
207  p2->count = dist_b;
208  p2->val = Tval;
209 
210  p2->next = p->next;
211  p->next = p2;
212  }
213 
214  return 0;
215  }
216  cur_x += p->count;
217  prev = p;
218  p = p->next;
219  }
220 
221  return 0;
222 }
223 
224 /*!
225  * \brief
226  *
227  * Returns sparse bitmap value at location 'x'/'y'
228  *
229  * Returns value or -1 on error
230  *
231  * \param map
232  * \param x
233  * \param y
234  * \return int
235  */
236 int BM_get_sparse(struct BM *map, int x, int y)
237 {
238  struct BMlink *p;
239  int cur_x = 0;
240 
241  p = ((struct BMlink **)(map->data))[y];
242  while (p != NULL) {
243  if (cur_x + p->count > x)
244  return (p->val);
245  cur_x += p->count;
246  p = p->next;
247  }
248 
249  return -1;
250 }
251 
252 /*!
253  * \brief
254  *
255  * Returns size of sparse bitmap in bytes
256  *
257  * \param map
258  * \return int
259  */
260 size_t BM_get_map_size_sparse(struct BM *map)
261 {
262  int i;
263  size_t size;
264  struct BMlink *p;
265 
266  size = (size_t)map->rows * sizeof(struct BMlink *);
267  for (i = 0; i < map->rows; i++) {
268  p = ((struct BMlink **)(map->data))[i];
269  while (p != NULL) {
270  size += sizeof(struct BMlink);
271  p = p->next;
272  }
273  }
274 
275  return size;
276 }
277 
278 /*!
279  * \brief
280  *
281  * Debugging code to dump out structure of links
282  *
283  * Returns 0
284  *
285  * \param map
286  * \return int
287  */
288 int BM_dump_map_sparse(struct BM *map)
289 {
290  int i;
291  struct BMlink *p;
292 
293  for (i = 0; i < map->rows; i++) {
294  p = ((struct BMlink **)(map->data))[i];
295  while (p != NULL) {
296  fprintf(stdout, "(%2d %2d) ", p->count, p->val);
297  p = p->next;
298  }
299  fprintf(stdout, "\n");
300  }
301 
302  return 0;
303 }
304 
305 /*!
306  * \brief
307  *
308  * Debugging code to dump out structure of links for single row
309  *
310  * Returns 0
311  *
312  * \param map
313  * \param y
314  * \return int
315  */
316 int BM_dump_map_row_sparse(struct BM *map, int y)
317 {
318  int i;
319  struct BMlink *p;
320 
321  i = y;
322  {
323  p = ((struct BMlink **)(map->data))[i];
324  while (p != NULL) {
325  fprintf(stdout, "(%2d %2d) ", p->count, p->val);
326  p = p->next;
327  }
328  fprintf(stdout, "\n");
329  }
330 
331  return 0;
332 }
333 
334 /*!
335  * \brief
336  *
337  * Write sparse bitmap matrix out to disk file 'fp'.
338  * NOTE: 'fp' must already be opened and later closed by user
339  *
340  * Returns 0 on success or -1 on error
341  *
342  * \param fp
343  * \param map
344  * \return int
345  */
346 int BM_file_write_sparse(FILE *fp, struct BM *map)
347 {
348  char c;
349  int i, y;
350  struct BMlink *p;
351 
352  c = BM_MAGIC;
353  fwrite(&c, sizeof(char), sizeof(char), fp);
354 
355  fwrite(BM_TEXT, BM_TEXT_LEN, sizeof(char), fp);
356 
357  c = BM_SPARSE;
358  fwrite(&c, sizeof(char), sizeof(char), fp);
359 
360  fwrite(&(map->rows), sizeof(map->rows), sizeof(char), fp);
361 
362  fwrite(&(map->cols), sizeof(map->cols), sizeof(char), fp);
363 
364  for (y = 0; y < map->rows; y++) {
365  /* first count number of links */
366  p = ((struct BMlink **)(map->data))[y];
367  int cnt = 0;
368 
369  while (p != NULL) {
370  cnt++;
371  p = p->next;
372  }
373 
374  i = cnt;
375  fwrite(&i, sizeof(i), sizeof(char), fp);
376 
377  /* then write them out */
378  p = ((struct BMlink **)(map->data))[y];
379  while (p != NULL) {
380  i = p->count;
381  fwrite(&i, sizeof(i), sizeof(char), fp);
382 
383  i = p->val;
384  fwrite(&i, sizeof(i), sizeof(char), fp);
385 
386  p = p->next;
387  }
388  }
389  fflush(fp);
390 
391  return 0;
392 }
#define BM_TEXT
Definition: bitmap.h:6
#define BM_TEXT_LEN
Definition: bitmap.h:7
#define BM_SPARSE
Definition: bitmap.h:11
#define BM_MAGIC
Definition: bitmap.h:4
#define NULL
Definition: ccmath.h:32
struct link_head * link_init(int)
Definition: linkm/init.c:42
void link_dispose(struct link_head *, VOID_T *)
void link_set_chunk_size(int)
Definition: linkm/init.c:32
void link_cleanup(struct link_head *)
Definition: linkm/init.c:67
VOID_T * link_new(struct link_head *)
Definition: new.c:12
double cur_x
Definition: driver/init.c:32
int count
#define VOID_T
Definition: linkm.h:8
struct BM * BM_create_sparse(int x, int y)
Create a sparse bitmap of dimension 'x'/'y'.
Definition: sparse.c:41
int BM_dump_map_row_sparse(struct BM *map, int y)
Debugging code to dump out structure of links for single row.
Definition: sparse.c:316
int BM_file_write_sparse(FILE *fp, struct BM *map)
Write sparse bitmap matrix out to disk file 'fp'. NOTE: 'fp' must already be opened and later closed ...
Definition: sparse.c:346
int BM_get_sparse(struct BM *map, int x, int y)
Returns sparse bitmap value at location 'x'/'y'.
Definition: sparse.c:236
size_t BM_get_map_size_sparse(struct BM *map)
Returns size of sparse bitmap in bytes.
Definition: sparse.c:260
int BM_destroy_sparse(struct BM *map)
Destroy sparse bitmap and free all associated memory.
Definition: sparse.c:86
int BM_set_sparse(struct BM *map, int x, int y, int val)
Set sparse bitmap value to 'val' at location 'x'/'y'.
Definition: sparse.c:122
int BM_dump_map_sparse(struct BM *map)
Debugging code to dump out structure of links.
Definition: sparse.c:288
void * malloc(unsigned)
void free(void *)
Definition: bitmap.h:17
int rows
Definition: bitmap.h:18
struct link_head * token
Definition: bitmap.h:24
int cols
Definition: bitmap.h:19
unsigned char * data
Definition: bitmap.h:21
size_t bytes
Definition: bitmap.h:20
int sparse
Definition: bitmap.h:22
#define x