GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
Loading...
Searching...
No Matches
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
28static 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 */
41struct 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 */
86int 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 */
122int 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 */
236int 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 */
260size_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 */
288int 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 */
316int 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 */
346int 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
VOID_T * link_new(struct link_head *)
Definition new.c:12
void link_dispose(struct link_head *, VOID_T *)
void link_set_chunk_size(int)
Definition linkm/init.c:32
struct link_head * link_init(int)
Definition linkm/init.c:42
void link_cleanup(struct link_head *)
Definition linkm/init.c:67
double cur_x
Definition driver/init.c:32
#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