1 |
/*<html><pre> -<a href="qh-set.htm" |
2 |
>-------------------------------</a><a name="TOP">-</a> |
3 |
|
4 |
qset.h |
5 |
header file for qset.c that implements set |
6 |
|
7 |
see qh-set.htm and qset.c |
8 |
|
9 |
only uses mem.c, malloc/free |
10 |
|
11 |
for error handling, writes message and calls |
12 |
qh_errexit (qhmem_ERRqhull, NULL, NULL); |
13 |
|
14 |
set operations satisfy the following properties: |
15 |
- sets have a max size, the actual size (if different) is stored at the end |
16 |
- every set is NULL terminated |
17 |
- sets may be sorted or unsorted, the caller must distinguish this |
18 |
|
19 |
copyright (c) 1993-2003, The Geometry Center |
20 |
*/ |
21 |
|
22 |
#ifndef qhDEFset |
23 |
#define qhDEFset 1 |
24 |
|
25 |
/*================= -structures- ===============*/ |
26 |
|
27 |
#ifndef DEFsetT |
28 |
#define DEFsetT 1 |
29 |
typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */ |
30 |
#endif |
31 |
|
32 |
/*-<a href="qh-set.htm#TOC" |
33 |
>----------------------------------------</a><a name="setT">-</a> |
34 |
|
35 |
setT |
36 |
a set or list of pointers with maximum size and actual size. |
37 |
|
38 |
variations: |
39 |
unsorted, unique -- a list of unique pointers with NULL terminator |
40 |
user guarantees uniqueness |
41 |
sorted -- a sorted list of unique pointers with NULL terminator |
42 |
qset.c guarantees uniqueness |
43 |
unsorted -- a list of pointers terminated with NULL |
44 |
indexed -- an array of pointers with NULL elements |
45 |
|
46 |
structure for set of n elements: |
47 |
|
48 |
-------------- |
49 |
| maxsize |
50 |
-------------- |
51 |
| e[0] - a pointer, may be NULL for indexed sets |
52 |
-------------- |
53 |
| e[1] |
54 |
|
55 |
-------------- |
56 |
| ... |
57 |
-------------- |
58 |
| e[n-1] |
59 |
-------------- |
60 |
| e[n] = NULL |
61 |
-------------- |
62 |
| ... |
63 |
-------------- |
64 |
| e[maxsize] - n+1 or NULL (determines actual size of set) |
65 |
-------------- |
66 |
|
67 |
*/ |
68 |
|
69 |
/*-- setelemT -- internal type to allow both pointers and indices |
70 |
*/ |
71 |
typedef union setelemT setelemT; |
72 |
union setelemT { |
73 |
void *p; |
74 |
int i; /* integer used for e[maxSize] */ |
75 |
}; |
76 |
|
77 |
struct setT { |
78 |
int maxsize; /* maximum number of elements (except NULL) */ |
79 |
setelemT e[1]; /* array of pointers, tail is NULL */ |
80 |
/* last slot (unless NULL) is actual size+1 |
81 |
e[maxsize]==NULL or e[e[maxsize]-1]==NULL */ |
82 |
/* this may generate a warning since e[] contains |
83 |
maxsize elements */ |
84 |
}; |
85 |
|
86 |
/*=========== -constants- =========================*/ |
87 |
|
88 |
/*-<a href="qh-set.htm#TOC" |
89 |
>-----------------------------------</a><a name="SETelemsize">-</a> |
90 |
|
91 |
SETelemsize |
92 |
size of a set element in bytes |
93 |
*/ |
94 |
#define SETelemsize sizeof(setelemT) |
95 |
|
96 |
|
97 |
/*=========== -macros- =========================*/ |
98 |
|
99 |
/*-<a href="qh-set.htm#TOC" |
100 |
>-----------------------------------</a><a name="FOREACHsetelement_">-</a> |
101 |
|
102 |
FOREACHsetelement_(type, set, variable) |
103 |
define FOREACH iterator |
104 |
|
105 |
declare: |
106 |
assumes *variable and **variablep are declared |
107 |
no space in "variable)" [DEC Alpha cc compiler] |
108 |
|
109 |
each iteration: |
110 |
variable is set element |
111 |
variablep is one beyond variable. |
112 |
|
113 |
to repeat an element: |
114 |
variablep--; / *repeat* / |
115 |
|
116 |
at exit: |
117 |
variable is NULL at end of loop |
118 |
|
119 |
example: |
120 |
#define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet ) |
121 |
|
122 |
notes: |
123 |
please use FOREACHsetelement_i_() if need index or include NULLs |
124 |
|
125 |
WARNING: |
126 |
nested loops can't use the same variable (define another FOREACH) |
127 |
|
128 |
needs braces if nested inside another FOREACH |
129 |
this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} ) |
130 |
*/ |
131 |
#define FOREACHsetelement_(type, set, variable) \ |
132 |
if (((variable= NULL), set)) for(\ |
133 |
variable##p= (type **)&((set)->e[0].p); \ |
134 |
(variable= *variable##p++);) |
135 |
|
136 |
/*-<a href="qh-set.htm#TOC" |
137 |
>----------------------------------------</a><a name="FOREACHsetelement_i_">-</a> |
138 |
|
139 |
FOREACHsetelement_i_(type, set, variable) |
140 |
define indexed FOREACH iterator |
141 |
|
142 |
declare: |
143 |
type *variable, variable_n, variable_i; |
144 |
|
145 |
each iteration: |
146 |
variable is set element, may be NULL |
147 |
variable_i is index, variable_n is qh_setsize() |
148 |
|
149 |
to repeat an element: |
150 |
variable_i--; variable_n-- repeats for deleted element |
151 |
|
152 |
at exit: |
153 |
variable==NULL and variable_i==variable_n |
154 |
|
155 |
example: |
156 |
#define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet ) |
157 |
|
158 |
WARNING: |
159 |
nested loops can't use the same variable (define another FOREACH) |
160 |
|
161 |
needs braces if nested inside another FOREACH |
162 |
this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} ) |
163 |
*/ |
164 |
#define FOREACHsetelement_i_(type, set, variable) \ |
165 |
if (((variable= NULL), set)) for (\ |
166 |
variable##_i= 0, variable= (type *)((set)->e[0].p), \ |
167 |
variable##_n= qh_setsize(set);\ |
168 |
variable##_i < variable##_n;\ |
169 |
variable= (type *)((set)->e[++variable##_i].p) ) |
170 |
|
171 |
/*-<a href="qh-set.htm#TOC" |
172 |
>--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a> |
173 |
|
174 |
FOREACHsetelementreverse_(type, set, variable)- |
175 |
define FOREACH iterator in reverse order |
176 |
|
177 |
declare: |
178 |
assumes *variable and **variablep are declared |
179 |
also declare 'int variabletemp' |
180 |
|
181 |
each iteration: |
182 |
variable is set element |
183 |
|
184 |
to repeat an element: |
185 |
variabletemp++; / *repeat* / |
186 |
|
187 |
at exit: |
188 |
variable is NULL |
189 |
|
190 |
example: |
191 |
#define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex ) |
192 |
|
193 |
notes: |
194 |
please use FOREACHsetelementreverse12_() to reverse first two elements |
195 |
WARNING: needs braces if nested inside another FOREACH |
196 |
*/ |
197 |
#define FOREACHsetelementreverse_(type, set, variable) \ |
198 |
if (((variable= NULL), set)) for(\ |
199 |
variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\ |
200 |
variable; variable= \ |
201 |
((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL)) |
202 |
|
203 |
/*-<a href="qh-set.htm#TOC" |
204 |
>-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a> |
205 |
|
206 |
FOREACHsetelementreverse12_(type, set, variable)- |
207 |
define FOREACH iterator with e[1] and e[0] reversed |
208 |
|
209 |
declare: |
210 |
assumes *variable and **variablep are declared |
211 |
|
212 |
each iteration: |
213 |
variable is set element |
214 |
variablep is one after variable. |
215 |
|
216 |
to repeat an element: |
217 |
variablep--; / *repeat* / |
218 |
|
219 |
at exit: |
220 |
variable is NULL at end of loop |
221 |
|
222 |
example |
223 |
#define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex ) |
224 |
|
225 |
notes: |
226 |
WARNING: needs braces if nested inside another FOREACH |
227 |
*/ |
228 |
#define FOREACHsetelementreverse12_(type, set, variable) \ |
229 |
if (((variable= NULL), set)) for(\ |
230 |
variable##p= (type **)&((set)->e[1].p); \ |
231 |
(variable= *variable##p); \ |
232 |
variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \ |
233 |
(variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++)) |
234 |
|
235 |
/*-<a href="qh-set.htm#TOC" |
236 |
>-----------------------------------</a><a name="FOREACHelem_">-</a> |
237 |
|
238 |
FOREACHelem_( set )- |
239 |
iterate elements in a set |
240 |
|
241 |
declare: |
242 |
void *elem, *elemp; |
243 |
|
244 |
each iteration: |
245 |
elem is set element |
246 |
elemp is one beyond |
247 |
|
248 |
to repeat an element: |
249 |
elemp--; / *repeat* / |
250 |
|
251 |
at exit: |
252 |
elem == NULL at end of loop |
253 |
|
254 |
example: |
255 |
FOREACHelem_(set) { |
256 |
|
257 |
notes: |
258 |
WARNING: needs braces if nested inside another FOREACH |
259 |
*/ |
260 |
#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem) |
261 |
|
262 |
/*-<a href="qh-set.htm#TOC" |
263 |
>-----------------------------------</a><a name="FOREACHset_">-</a> |
264 |
|
265 |
FOREACHset_( set )- |
266 |
iterate a set of sets |
267 |
|
268 |
declare: |
269 |
setT *set, **setp; |
270 |
|
271 |
each iteration: |
272 |
set is set element |
273 |
setp is one beyond |
274 |
|
275 |
to repeat an element: |
276 |
setp--; / *repeat* / |
277 |
|
278 |
at exit: |
279 |
set == NULL at end of loop |
280 |
|
281 |
example |
282 |
FOREACHset_(sets) { |
283 |
|
284 |
notes: |
285 |
WARNING: needs braces if nested inside another FOREACH |
286 |
*/ |
287 |
#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set) |
288 |
|
289 |
/*-<a href="qh-set.htm#TOC" |
290 |
>-----------------------------------------</a><a name="SETindex_">-</a> |
291 |
|
292 |
SETindex_( set, elem ) |
293 |
return index of elem in set |
294 |
|
295 |
notes: |
296 |
for use with FOREACH iteration |
297 |
|
298 |
example: |
299 |
i= SETindex_(ridges, ridge) |
300 |
*/ |
301 |
#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p) |
302 |
|
303 |
/*-<a href="qh-set.htm#TOC" |
304 |
>---------------------------------------</a><a name="SETref_">-</a> |
305 |
|
306 |
SETref_( elem ) |
307 |
l.h.s. for modifying the current element in a FOREACH iteration |
308 |
|
309 |
example: |
310 |
SETref_(ridge)= anotherridge; |
311 |
*/ |
312 |
#define SETref_(elem) (elem##p[-1]) |
313 |
|
314 |
/*-<a href="qh-set.htm#TOC" |
315 |
>---------------------------------------</a><a name="SETelem_">-</a> |
316 |
|
317 |
SETelem_(set, n) |
318 |
return the n'th element of set |
319 |
|
320 |
notes: |
321 |
assumes that n is valid [0..size] and that set is defined |
322 |
please use SETelemt_() for type cast |
323 |
*/ |
324 |
#define SETelem_(set, n) ((set)->e[n].p) |
325 |
|
326 |
/*-<a href="qh-set.htm#TOC" |
327 |
>---------------------------------------</a><a name="SETelemt_">-</a> |
328 |
|
329 |
SETelemt_(set, n, type) |
330 |
return the n'th element of set as a type |
331 |
|
332 |
notes: |
333 |
assumes that n is valid [0..size] and that set is defined |
334 |
*/ |
335 |
#define SETelemt_(set, n, type) ((type*)((set)->e[n].p)) |
336 |
|
337 |
/*-<a href="qh-set.htm#TOC" |
338 |
>---------------------------------------</a><a name="SETelemaddr_">-</a> |
339 |
|
340 |
SETelemaddr_(set, n, type) |
341 |
return address of the n'th element of a set |
342 |
|
343 |
notes: |
344 |
assumes that n is valid [0..size] and set is defined |
345 |
*/ |
346 |
#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p))) |
347 |
|
348 |
/*-<a href="qh-set.htm#TOC" |
349 |
>---------------------------------------</a><a name="SETfirst_">-</a> |
350 |
|
351 |
SETfirst_(set) |
352 |
return first element of set |
353 |
|
354 |
*/ |
355 |
#define SETfirst_(set) ((set)->e[0].p) |
356 |
|
357 |
/*-<a href="qh-set.htm#TOC" |
358 |
>---------------------------------------</a><a name="SETfirstt_">-</a> |
359 |
|
360 |
SETfirstt_(set, type) |
361 |
return first element of set as a type |
362 |
|
363 |
*/ |
364 |
#define SETfirstt_(set, type) ((type*)((set)->e[0].p)) |
365 |
|
366 |
/*-<a href="qh-set.htm#TOC" |
367 |
>---------------------------------------</a><a name="SETsecond_">-</a> |
368 |
|
369 |
SETsecond_(set) |
370 |
return second element of set |
371 |
|
372 |
*/ |
373 |
#define SETsecond_(set) ((set)->e[1].p) |
374 |
|
375 |
/*-<a href="qh-set.htm#TOC" |
376 |
>---------------------------------------</a><a name="SETsecondt_">-</a> |
377 |
|
378 |
SETsecondt_(set, type) |
379 |
return second element of set as a type |
380 |
*/ |
381 |
#define SETsecondt_(set, type) ((type*)((set)->e[1].p)) |
382 |
|
383 |
/*-<a href="qh-set.htm#TOC" |
384 |
>---------------------------------------</a><a name="SETaddr_">-</a> |
385 |
|
386 |
SETaddr_(set, type) |
387 |
return address of set's elements |
388 |
*/ |
389 |
#define SETaddr_(set,type) ((type **)(&((set)->e[0].p))) |
390 |
|
391 |
/*-<a href="qh-set.htm#TOC" |
392 |
>---------------------------------------</a><a name="SETreturnsize_">-</a> |
393 |
|
394 |
SETreturnsize_(set, size) |
395 |
return size of a set |
396 |
|
397 |
notes: |
398 |
set must be defined |
399 |
please use qh_setsize(set) unless speed is critical |
400 |
*/ |
401 |
#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize)) |
402 |
|
403 |
/*-<a href="qh-set.htm#TOC" |
404 |
>---------------------------------------</a><a name="SETempty_">-</a> |
405 |
|
406 |
SETempty_(set) |
407 |
return true (1) if set is empty |
408 |
|
409 |
notes: |
410 |
set may be NULL |
411 |
*/ |
412 |
#define SETempty_(set) (!set || (SETfirst_(set) ? 0:1)) |
413 |
|
414 |
/*-<a href="qh-set.htm#TOC" |
415 |
>---------------------------------------</a><a name="SETtruncate_">-</a> |
416 |
|
417 |
SETtruncate_(set) |
418 |
return first element of set |
419 |
|
420 |
see: |
421 |
qh_settruncate() |
422 |
|
423 |
*/ |
424 |
#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; \ |
425 |
set->e[size].p= NULL;} |
426 |
|
427 |
/*======= prototypes in alphabetical order ============*/ |
428 |
|
429 |
void qh_setaddsorted(setT **setp, void *elem); |
430 |
void qh_setaddnth(setT **setp, int nth, void *newelem); |
431 |
void qh_setappend(setT **setp, void *elem); |
432 |
void qh_setappend_set(setT **setp, setT *setA); |
433 |
void qh_setappend2ndlast(setT **setp, void *elem); |
434 |
void qh_setcheck(setT *set, char *tname, int id); |
435 |
void qh_setcompact(setT *set); |
436 |
setT *qh_setcopy(setT *set, int extra); |
437 |
void *qh_setdel(setT *set, void *elem); |
438 |
void *qh_setdellast(setT *set); |
439 |
void *qh_setdelnth(setT *set, int nth); |
440 |
void *qh_setdelnthsorted(setT *set, int nth); |
441 |
void *qh_setdelsorted(setT *set, void *newelem); |
442 |
setT *qh_setduplicate( setT *set, int elemsize); |
443 |
int qh_setequal(setT *setA, setT *setB); |
444 |
int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB); |
445 |
int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB); |
446 |
void qh_setfree(setT **set); |
447 |
void qh_setfree2( setT **setp, int elemsize); |
448 |
void qh_setfreelong(setT **set); |
449 |
int qh_setin(setT *set, void *setelem); |
450 |
int qh_setindex(setT *set, void *setelem); |
451 |
void qh_setlarger(setT **setp); |
452 |
void *qh_setlast(setT *set); |
453 |
setT *qh_setnew(int size); |
454 |
setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend); |
455 |
void qh_setprint(FILE *fp, char* string, setT *set); |
456 |
void qh_setreplace(setT *set, void *oldelem, void *newelem); |
457 |
int qh_setsize(setT *set); |
458 |
setT *qh_settemp(int setsize); |
459 |
void qh_settempfree(setT **set); |
460 |
void qh_settempfree_all(void); |
461 |
setT *qh_settemppop(void); |
462 |
void qh_settemppush(setT *set); |
463 |
void qh_settruncate (setT *set, int size); |
464 |
int qh_setunique (setT **set, void *elem); |
465 |
void qh_setzero (setT *set, int index, int size); |
466 |
|
467 |
|
468 |
#endif /* qhDEFset */ |