ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/QuickHull/qset.c
Revision: 3138
Committed: Tue May 29 22:51:00 2007 UTC (17 years, 11 months ago) by chuckv
Content type: text/plain
File size: 31985 byte(s)
Log Message:
Addded QuickHull to cvs.

File Contents

# Content
1 /*<html><pre> -<a href="qh-set.htm"
2 >-------------------------------</a><a name="TOP">-</a>
3
4 qset.c
5 implements set manipulations needed for quickhull
6
7 see qh-set.htm and qset.h
8
9 copyright (c) 1993-2003 The Geometry Center
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 /*** uncomment here and qhull_a.h
15 if string.h does not define memcpy()
16 #include <memory.h>
17 */
18 #include "config.h"
19 #include "QuickHull/qset.h"
20 #include "QuickHull/mem.h"
21
22 #ifndef qhDEFqhull
23 typedef struct ridgeT ridgeT;
24 typedef struct facetT facetT;
25 void qh_errexit(int exitcode, facetT *, ridgeT *);
26 #endif
27
28 /*=============== internal macros ===========================*/
29
30 /*-<a href="qh-set.htm#TOC"
31 >-------------------------------<a name="SETsizeaddr_">-</a>
32
33 SETsizeaddr_(set)
34 return pointer to actual size+1 of set (set CANNOT be NULL!!)
35
36 notes:
37 *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
38 */
39 #define SETsizeaddr_(set) (&((set)->e[(set)->maxsize].i))
40
41 /*============ functions in alphabetical order ===================*/
42
43 /*-<a href="qh-set.htm#TOC"
44 >--------------------------------<a name="setaddnth">-</a>
45
46 qh_setaddnth( setp, nth, newelem)
47 adds newelem as n'th element of sorted or unsorted *setp
48
49 notes:
50 *setp and newelem must be defined
51 *setp may be a temp set
52 nth=0 is first element
53 errors if nth is out of bounds
54
55 design:
56 expand *setp if empty or full
57 move tail of *setp up one
58 insert newelem
59 */
60 void qh_setaddnth(setT **setp, int nth, void *newelem) {
61 int *sizep, oldsize, i;
62 void **oldp, **newp;
63
64 if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
65 qh_setlarger(setp);
66 sizep= SETsizeaddr_(*setp);
67 }
68 oldsize= *sizep - 1;
69 if (nth < 0 || nth > oldsize) {
70 fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
71 qh_setprint (qhmem.ferr, "", *setp);
72 qh_errexit (qhmem_ERRqhull, NULL, NULL);
73 }
74 (*sizep)++;
75 oldp= SETelemaddr_(*setp, oldsize, void); /* NULL */
76 newp= oldp+1;
77 for (i= oldsize-nth+1; i--; ) /* move at least NULL */
78 *(newp--)= *(oldp--); /* may overwrite *sizep */
79 *newp= newelem;
80 } /* setaddnth */
81
82
83 /*-<a href="qh-set.htm#TOC"
84 >--------------------------------<a name="setaddsorted">-</a>
85
86 setaddsorted( setp, newelem )
87 adds an newelem into sorted *setp
88
89 notes:
90 *setp and newelem must be defined
91 *setp may be a temp set
92 nop if newelem already in set
93
94 design:
95 find newelem's position in *setp
96 insert newelem
97 */
98 void qh_setaddsorted(setT **setp, void *newelem) {
99 int newindex=0;
100 void *elem, **elemp;
101
102 FOREACHelem_(*setp) { /* could use binary search instead */
103 if (elem < newelem)
104 newindex++;
105 else if (elem == newelem)
106 return;
107 else
108 break;
109 }
110 qh_setaddnth(setp, newindex, newelem);
111 } /* setaddsorted */
112
113
114 /*-<a href="qh-set.htm#TOC"
115 >-------------------------------<a name="setappend">-</a>
116
117 qh_setappend( setp, newelem)
118 append newelem to *setp
119
120 notes:
121 *setp may be a temp set
122 *setp and newelem may be NULL
123
124 design:
125 expand *setp if empty or full
126 append newelem to *setp
127
128 */
129 void qh_setappend(setT **setp, void *newelem) {
130 int *sizep;
131 void **endp;
132
133 if (!newelem)
134 return;
135 if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
136 qh_setlarger(setp);
137 sizep= SETsizeaddr_(*setp);
138 }
139 *(endp= &((*setp)->e[(*sizep)++ - 1].p))= newelem;
140 *(++endp)= NULL;
141 } /* setappend */
142
143 /*-<a href="qh-set.htm#TOC"
144 >-------------------------------<a name="setappend_set">-</a>
145
146 qh_setappend_set( setp, setA)
147 appends setA to *setp
148
149 notes:
150 *setp can not be a temp set
151 *setp and setA may be NULL
152
153 design:
154 setup for copy
155 expand *setp if it is too small
156 append all elements of setA to *setp
157 */
158 void qh_setappend_set(setT **setp, setT *setA) {
159 int *sizep, sizeA, size;
160 setT *oldset;
161
162 if (!setA)
163 return;
164 SETreturnsize_(setA, sizeA);
165 if (!*setp)
166 *setp= qh_setnew (sizeA);
167 sizep= SETsizeaddr_(*setp);
168 if (!(size= *sizep))
169 size= (*setp)->maxsize;
170 else
171 size--;
172 if (size + sizeA > (*setp)->maxsize) {
173 oldset= *setp;
174 *setp= qh_setcopy (oldset, sizeA);
175 qh_setfree (&oldset);
176 sizep= SETsizeaddr_(*setp);
177 }
178 *sizep= size+sizeA+1; /* memcpy may overwrite */
179 if (sizeA > 0)
180 memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), SETelemsize *(sizeA+1));
181 } /* setappend_set */
182
183
184 /*-<a href="qh-set.htm#TOC"
185 >-------------------------------<a name="setappend2ndlast">-</a>
186
187 qh_setappend2ndlast( setp, newelem )
188 makes newelem the next to the last element in *setp
189
190 notes:
191 *setp must have at least one element
192 newelem must be defined
193 *setp may be a temp set
194
195 design:
196 expand *setp if empty or full
197 move last element of *setp up one
198 insert newelem
199 */
200 void qh_setappend2ndlast(setT **setp, void *newelem) {
201 int *sizep;
202 void **endp, **lastp;
203
204 if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
205 qh_setlarger(setp);
206 sizep= SETsizeaddr_(*setp);
207 }
208 endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */
209 lastp= endp-1;
210 *(endp++)= *lastp;
211 *endp= NULL; /* may overwrite *sizep */
212 *lastp= newelem;
213 } /* setappend2ndlast */
214
215
216 /*-<a href="qh-set.htm#TOC"
217 >-------------------------------<a name="setcheck">-</a>
218
219 qh_setcheck( set, typename, id )
220 check set for validity
221 report errors with typename and id
222
223 design:
224 checks that maxsize, actual size, and NULL terminator agree
225 */
226 void qh_setcheck(setT *set, char *tname, int id) {
227 int maxsize, size;
228 int waserr= 0;
229
230 if (!set)
231 return;
232 SETreturnsize_(set, size);
233 maxsize= set->maxsize;
234 if (size > maxsize || !maxsize) {
235 fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
236 size, tname, id, maxsize);
237 waserr= 1;
238 }else if (set->e[size].p) {
239 fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): %s%d (size %d max %d) is not null terminated.\n",
240 tname, id, maxsize, size-1);
241 waserr= 1;
242 }
243 if (waserr) {
244 qh_setprint (qhmem.ferr, "ERRONEOUS", set);
245 qh_errexit (qhmem_ERRqhull, NULL, NULL);
246 }
247 } /* setcheck */
248
249
250 /*-<a href="qh-set.htm#TOC"
251 >-------------------------------<a name="setcompact">-</a>
252
253 qh_setcompact( set )
254 remove internal NULLs from an unsorted set
255
256 returns:
257 updated set
258
259 notes:
260 set may be NULL
261 it would be faster to swap tail of set into holes, like qh_setdel
262
263 design:
264 setup pointers into set
265 skip NULLs while copying elements to start of set
266 update the actual size
267 */
268 void qh_setcompact(setT *set) {
269 int size;
270 void **destp, **elemp, **endp, **firstp;
271
272 if (!set)
273 return;
274 SETreturnsize_(set, size);
275 destp= elemp= firstp= SETaddr_(set, void);
276 endp= destp + size;
277 while (1) {
278 if (!(*destp++ = *elemp++)) {
279 destp--;
280 if (elemp > endp)
281 break;
282 }
283 }
284 qh_settruncate (set, destp-firstp);
285 } /* setcompact */
286
287
288 /*-<a href="qh-set.htm#TOC"
289 >-------------------------------<a name="setcopy">-</a>
290
291 qh_setcopy( set, extra )
292 make a copy of a sorted or unsorted set with extra slots
293
294 returns:
295 new set
296
297 design:
298 create a newset with extra slots
299 copy the elements to the newset
300
301 */
302 setT *qh_setcopy(setT *set, int extra) {
303 setT *newset;
304 int size;
305
306 if (extra < 0)
307 extra= 0;
308 SETreturnsize_(set, size);
309 newset= qh_setnew(size+extra);
310 *SETsizeaddr_(newset)= size+1; /* memcpy may overwrite */
311 memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), SETelemsize *(size+1));
312 return (newset);
313 } /* setcopy */
314
315
316 /*-<a href="qh-set.htm#TOC"
317 >-------------------------------<a name="setdel">-</a>
318
319 qh_setdel( set, oldelem )
320 delete oldelem from an unsorted set
321
322 returns:
323 returns oldelem if found
324 returns NULL otherwise
325
326 notes:
327 set may be NULL
328 oldelem must not be NULL;
329 only deletes one copy of oldelem in set
330
331 design:
332 locate oldelem
333 update actual size if it was full
334 move the last element to the oldelem's location
335 */
336 void *qh_setdel(setT *set, void *oldelem) {
337 void **elemp, **lastp;
338 int *sizep;
339
340 if (!set)
341 return NULL;
342 elemp= SETaddr_(set, void);
343 while (*elemp != oldelem && *elemp)
344 elemp++;
345 if (*elemp) {
346 sizep= SETsizeaddr_(set);
347 if (!(*sizep)--) /* if was a full set */
348 *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
349 lastp= SETelemaddr_(set, *sizep-1, void);
350 *elemp= *lastp; /* may overwrite itself */
351 *lastp= NULL;
352 return oldelem;
353 }
354 return NULL;
355 } /* setdel */
356
357
358 /*-<a href="qh-set.htm#TOC"
359 >-------------------------------<a name="setdellast">-</a>
360
361 qh_setdellast( set)
362 return last element of set or NULL
363
364 notes:
365 deletes element from set
366 set may be NULL
367
368 design:
369 return NULL if empty
370 if full set
371 delete last element and set actual size
372 else
373 delete last element and update actual size
374 */
375 void *qh_setdellast(setT *set) {
376 int setsize; /* actually, actual_size + 1 */
377 int maxsize;
378 int *sizep;
379 void *returnvalue;
380
381 if (!set || !(set->e[0].p))
382 return NULL;
383 sizep= SETsizeaddr_(set);
384 if ((setsize= *sizep)) {
385 returnvalue= set->e[setsize - 2].p;
386 set->e[setsize - 2].p= NULL;
387 (*sizep)--;
388 }else {
389 maxsize= set->maxsize;
390 returnvalue= set->e[maxsize - 1].p;
391 set->e[maxsize - 1].p= NULL;
392 *sizep= maxsize;
393 }
394 return returnvalue;
395 } /* setdellast */
396
397
398 /*-<a href="qh-set.htm#TOC"
399 >-------------------------------<a name="setdelnth">-</a>
400
401 qh_setdelnth( set, nth )
402 deletes nth element from unsorted set
403 0 is first element
404
405 returns:
406 returns the element (needs type conversion)
407
408 notes:
409 errors if nth invalid
410
411 design:
412 setup points and check nth
413 delete nth element and overwrite with last element
414 */
415 void *qh_setdelnth(setT *set, int nth) {
416 void **elemp, **lastp, *elem;
417 int *sizep;
418
419
420 elemp= SETelemaddr_(set, nth, void);
421 sizep= SETsizeaddr_(set);
422 if (!(*sizep)--) /* if was a full set */
423 *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
424 if (nth < 0 || nth >= *sizep) {
425 fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
426 qh_setprint (qhmem.ferr, "", set);
427 qh_errexit (qhmem_ERRqhull, NULL, NULL);
428 }
429 lastp= SETelemaddr_(set, *sizep-1, void);
430 elem= *elemp;
431 *elemp= *lastp; /* may overwrite itself */
432 *lastp= NULL;
433 return elem;
434 } /* setdelnth */
435
436 /*-<a href="qh-set.htm#TOC"
437 >-------------------------------<a name="setdelnthsorted">-</a>
438
439 qh_setdelnthsorted( set, nth )
440 deletes nth element from sorted set
441
442 returns:
443 returns the element (use type conversion)
444
445 notes:
446 errors if nth invalid
447
448 see also:
449 setnew_delnthsorted
450
451 design:
452 setup points and check nth
453 copy remaining elements down one
454 update actual size
455 */
456 void *qh_setdelnthsorted(setT *set, int nth) {
457 void **newp, **oldp, *elem;
458 int *sizep;
459
460 sizep= SETsizeaddr_(set);
461 if (nth < 0 || (*sizep && nth >= *sizep-1) || nth >= set->maxsize) {
462 fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
463 qh_setprint (qhmem.ferr, "", set);
464 qh_errexit (qhmem_ERRqhull, NULL, NULL);
465 }
466 newp= SETelemaddr_(set, nth, void);
467 elem= *newp;
468 oldp= newp+1;
469 while ((*(newp++)= *(oldp++)))
470 ; /* copy remaining elements and NULL */
471 if (!(*sizep)--) /* if was a full set */
472 *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */
473 return elem;
474 } /* setdelnthsorted */
475
476
477 /*-<a href="qh-set.htm#TOC"
478 >-------------------------------<a name="setdelsorted">-</a>
479
480 qh_setdelsorted( set, oldelem )
481 deletes oldelem from sorted set
482
483 returns:
484 returns oldelem if it was deleted
485
486 notes:
487 set may be NULL
488
489 design:
490 locate oldelem in set
491 copy remaining elements down one
492 update actual size
493 */
494 void *qh_setdelsorted(setT *set, void *oldelem) {
495 void **newp, **oldp;
496 int *sizep;
497
498 if (!set)
499 return NULL;
500 newp= SETaddr_(set, void);
501 while(*newp != oldelem && *newp)
502 newp++;
503 if (*newp) {
504 oldp= newp+1;
505 while ((*(newp++)= *(oldp++)))
506 ; /* copy remaining elements */
507 sizep= SETsizeaddr_(set);
508 if (!(*sizep)--) /* if was a full set */
509 *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */
510 return oldelem;
511 }
512 return NULL;
513 } /* setdelsorted */
514
515
516 /*-<a href="qh-set.htm#TOC"
517 >-------------------------------<a name="setduplicate">-</a>
518
519 qh_setduplicate( set, elemsize )
520 duplicate a set of elemsize elements
521
522 notes:
523 please use setcopy if retaining old elements
524
525 design:
526 create a new set
527 for each elem of the old set
528 create a newelem
529 append newelem to newset
530 */
531 setT *qh_setduplicate (setT *set, int elemsize) {
532 void *elem, **elemp, *newElem;
533 setT *newSet;
534 int size;
535
536 if (!(size= qh_setsize (set)))
537 return NULL;
538 newSet= qh_setnew (size);
539 FOREACHelem_(set) {
540 newElem= qh_memalloc (elemsize);
541 memcpy (newElem, elem, elemsize);
542 qh_setappend (&newSet, newElem);
543 }
544 return newSet;
545 } /* setduplicate */
546
547
548 /*-<a href="qh-set.htm#TOC"
549 >-------------------------------<a name="setequal">-</a>
550
551 qh_setequal( )
552 returns 1 if two sorted sets are equal, otherwise returns 0
553
554 notes:
555 either set may be NULL
556
557 design:
558 check size of each set
559 setup pointers
560 compare elements of each set
561 */
562 int qh_setequal(setT *setA, setT *setB) {
563 void **elemAp, **elemBp;
564 int sizeA, sizeB;
565
566 SETreturnsize_(setA, sizeA);
567 SETreturnsize_(setB, sizeB);
568 if (sizeA != sizeB)
569 return 0;
570 if (!sizeA)
571 return 1;
572 elemAp= SETaddr_(setA, void);
573 elemBp= SETaddr_(setB, void);
574 if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
575 return 1;
576 return 0;
577 } /* setequal */
578
579
580 /*-<a href="qh-set.htm#TOC"
581 >-------------------------------<a name="setequal_except">-</a>
582
583 qh_setequal_except( setA, skipelemA, setB, skipelemB )
584 returns 1 if sorted setA and setB are equal except for skipelemA & B
585
586 returns:
587 false if either skipelemA or skipelemB are missing
588
589 notes:
590 neither set may be NULL
591
592 if skipelemB is NULL,
593 can skip any one element of setB
594
595 design:
596 setup pointers
597 search for skipelemA, skipelemB, and mismatches
598 check results
599 */
600 int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
601 void **elemA, **elemB;
602 int skip=0;
603
604 elemA= SETaddr_(setA, void);
605 elemB= SETaddr_(setB, void);
606 while (1) {
607 if (*elemA == skipelemA) {
608 skip++;
609 elemA++;
610 }
611 if (skipelemB) {
612 if (*elemB == skipelemB) {
613 skip++;
614 elemB++;
615 }
616 }else if (*elemA != *elemB) {
617 skip++;
618 if (!(skipelemB= *elemB++))
619 return 0;
620 }
621 if (!*elemA)
622 break;
623 if (*elemA++ != *elemB++)
624 return 0;
625 }
626 if (skip != 2 || *elemB)
627 return 0;
628 return 1;
629 } /* setequal_except */
630
631
632 /*-<a href="qh-set.htm#TOC"
633 >-------------------------------<a name="setequal_skip">-</a>
634
635 qh_setequal_skip( setA, skipA, setB, skipB )
636 returns 1 if sorted setA and setB are equal except for elements skipA & B
637
638 returns:
639 false if different size
640
641 notes:
642 neither set may be NULL
643
644 design:
645 setup pointers
646 search for mismatches while skipping skipA and skipB
647 */
648 int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) {
649 void **elemA, **elemB, **skipAp, **skipBp;
650
651 elemA= SETaddr_(setA, void);
652 elemB= SETaddr_(setB, void);
653 skipAp= SETelemaddr_(setA, skipA, void);
654 skipBp= SETelemaddr_(setB, skipB, void);
655 while (1) {
656 if (elemA == skipAp)
657 elemA++;
658 if (elemB == skipBp)
659 elemB++;
660 if (!*elemA)
661 break;
662 if (*elemA++ != *elemB++)
663 return 0;
664 }
665 if (*elemB)
666 return 0;
667 return 1;
668 } /* setequal_skip */
669
670
671 /*-<a href="qh-set.htm#TOC"
672 >-------------------------------<a name="setfree">-</a>
673
674 qh_setfree( setp )
675 frees the space occupied by a sorted or unsorted set
676
677 returns:
678 sets setp to NULL
679
680 notes:
681 set may be NULL
682
683 design:
684 free array
685 free set
686 */
687 void qh_setfree(setT **setp) {
688 int size;
689 void **freelistp; /* used !qh_NOmem */
690
691 if (*setp) {
692 size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
693 if (size <= qhmem.LASTsize) {
694 qh_memfree_(*setp, size, freelistp);
695 }else
696 qh_memfree (*setp, size);
697 *setp= NULL;
698 }
699 } /* setfree */
700
701
702 /*-<a href="qh-set.htm#TOC"
703 >-------------------------------<a name="setfree2">-</a>
704
705 qh_setfree2( setp, elemsize )
706 frees the space occupied by a set and its elements
707
708 notes:
709 set may be NULL
710
711 design:
712 free each element
713 free set
714 */
715 void qh_setfree2 (setT **setp, int elemsize) {
716 void *elem, **elemp;
717
718 FOREACHelem_(*setp)
719 qh_memfree (elem, elemsize);
720 qh_setfree (setp);
721 } /* setfree2 */
722
723
724
725 /*-<a href="qh-set.htm#TOC"
726 >-------------------------------<a name="setfreelong">-</a>
727
728 qh_setfreelong( setp )
729 frees a set only if it's in long memory
730
731 returns:
732 sets setp to NULL if it is freed
733
734 notes:
735 set may be NULL
736
737 design:
738 if set is large
739 free it
740 */
741 void qh_setfreelong(setT **setp) {
742 int size;
743
744 if (*setp) {
745 size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
746 if (size > qhmem.LASTsize) {
747 qh_memfree (*setp, size);
748 *setp= NULL;
749 }
750 }
751 } /* setfreelong */
752
753
754 /*-<a href="qh-set.htm#TOC"
755 >-------------------------------<a name="setin">-</a>
756
757 qh_setin( set, setelem )
758 returns 1 if setelem is in a set, 0 otherwise
759
760 notes:
761 set may be NULL or unsorted
762
763 design:
764 scans set for setelem
765 */
766 int qh_setin(setT *set, void *setelem) {
767 void *elem, **elemp;
768
769 FOREACHelem_(set) {
770 if (elem == setelem)
771 return 1;
772 }
773 return 0;
774 } /* setin */
775
776
777 /*-<a href="qh-set.htm#TOC"
778 >-------------------------------<a name="setindex">-</a>
779
780 qh_setindex( set, atelem )
781 returns the index of atelem in set.
782 returns -1, if not in set or maxsize wrong
783
784 notes:
785 set may be NULL and may contain nulls.
786
787 design:
788 checks maxsize
789 scans set for atelem
790 */
791 int qh_setindex(setT *set, void *atelem) {
792 void **elem;
793 int size, i;
794
795 SETreturnsize_(set, size);
796 if (size > set->maxsize)
797 return -1;
798 elem= SETaddr_(set, void);
799 for (i=0; i < size; i++) {
800 if (*elem++ == atelem)
801 return i;
802 }
803 return -1;
804 } /* setindex */
805
806
807 /*-<a href="qh-set.htm#TOC"
808 >-------------------------------<a name="setlarger">-</a>
809
810 qh_setlarger( oldsetp )
811 returns a larger set that contains all elements of *oldsetp
812
813 notes:
814 the set is at least twice as large
815 if temp set, updates qhmem.tempstack
816
817 design:
818 creates a new set
819 copies the old set to the new set
820 updates pointers in tempstack
821 deletes the old set
822 */
823 void qh_setlarger(setT **oldsetp) {
824 int size= 1, *sizep;
825 setT *newset, *set, **setp, *oldset;
826 void **oldp, **newp;
827
828 if (*oldsetp) {
829 oldset= *oldsetp;
830 SETreturnsize_(oldset, size);
831 qhmem.cntlarger++;
832 qhmem.totlarger += size+1;
833 newset= qh_setnew(2 * size);
834 oldp= SETaddr_(oldset, void);
835 newp= SETaddr_(newset, void);
836 memcpy((char *)newp, (char *)oldp, (size+1) * SETelemsize);
837 sizep= SETsizeaddr_(newset);
838 *sizep= size+1;
839 FOREACHset_((setT *)qhmem.tempstack) {
840 if (set == oldset)
841 *(setp-1)= newset;
842 }
843 qh_setfree(oldsetp);
844 }else
845 newset= qh_setnew(3);
846 *oldsetp= newset;
847 } /* setlarger */
848
849
850 /*-<a href="qh-set.htm#TOC"
851 >-------------------------------<a name="setlast">-</a>
852
853 qh_setlast( )
854 return last element of set or NULL (use type conversion)
855
856 notes:
857 set may be NULL
858
859 design:
860 return last element
861 */
862 void *qh_setlast(setT *set) {
863 int size;
864
865 if (set) {
866 size= *SETsizeaddr_(set);
867 if (!size)
868 return SETelem_(set, set->maxsize - 1);
869 else if (size > 1)
870 return SETelem_(set, size - 2);
871 }
872 return NULL;
873 } /* setlast */
874
875
876 /*-<a href="qh-set.htm#TOC"
877 >-------------------------------<a name="setnew">-</a>
878
879 qh_setnew( setsize )
880 creates and allocates space for a set
881
882 notes:
883 setsize means the number of elements (NOT including the NULL terminator)
884 please use qh_settemp/qh_setfreetemp if set is temporary
885
886 design:
887 allocate memory for set
888 roundup memory if small set
889 initialize as empty set
890 */
891 setT *qh_setnew(int setsize) {
892 setT *set;
893 int sizereceived; /* used !qh_NOmem */
894 int size;
895 void **freelistp; /* used !qh_NOmem */
896
897 if (!setsize)
898 setsize++;
899 size= sizeof(setT) + setsize * SETelemsize;
900 if ((unsigned) size <= (unsigned) qhmem.LASTsize) {
901 qh_memalloc_(size, freelistp, set, setT);
902 #ifndef qh_NOmem
903 sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
904 if (sizereceived > size)
905 setsize += (sizereceived - size)/SETelemsize;
906 #endif
907 }else
908 set= (setT*)qh_memalloc (size);
909 set->maxsize= setsize;
910 set->e[setsize].i= 1;
911 set->e[0].p= NULL;
912 return (set);
913 } /* setnew */
914
915
916 /*-<a href="qh-set.htm#TOC"
917 >-------------------------------<a name="setnew_delnthsorted">-</a>
918
919 qh_setnew_delnthsorted( set, size, nth, prepend )
920 creates a sorted set not containing nth element
921 if prepend, the first prepend elements are undefined
922
923 notes:
924 set must be defined
925 checks nth
926 see also: setdelnthsorted
927
928 design:
929 create new set
930 setup pointers and allocate room for prepend'ed entries
931 append head of old set to new set
932 append tail of old set to new set
933 */
934 setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
935 setT *newset;
936 void **oldp, **newp;
937 int tailsize= size - nth -1, newsize;
938
939 if (tailsize < 0) {
940 fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
941 qh_setprint (qhmem.ferr, "", set);
942 qh_errexit (qhmem_ERRqhull, NULL, NULL);
943 }
944 newsize= size-1 + prepend;
945 newset= qh_setnew(newsize);
946 newset->e[newset->maxsize].i= newsize+1; /* may be overwritten */
947 oldp= SETaddr_(set, void);
948 newp= SETaddr_(newset, void) + prepend;
949 switch (nth) {
950 case 0:
951 break;
952 case 1:
953 *(newp++)= *oldp++;
954 break;
955 case 2:
956 *(newp++)= *oldp++;
957 *(newp++)= *oldp++;
958 break;
959 case 3:
960 *(newp++)= *oldp++;
961 *(newp++)= *oldp++;
962 *(newp++)= *oldp++;
963 break;
964 case 4:
965 *(newp++)= *oldp++;
966 *(newp++)= *oldp++;
967 *(newp++)= *oldp++;
968 *(newp++)= *oldp++;
969 break;
970 default:
971 memcpy((char *)newp, (char *)oldp, nth * SETelemsize);
972 newp += nth;
973 oldp += nth;
974 break;
975 }
976 oldp++;
977 switch (tailsize) {
978 case 0:
979 break;
980 case 1:
981 *(newp++)= *oldp++;
982 break;
983 case 2:
984 *(newp++)= *oldp++;
985 *(newp++)= *oldp++;
986 break;
987 case 3:
988 *(newp++)= *oldp++;
989 *(newp++)= *oldp++;
990 *(newp++)= *oldp++;
991 break;
992 case 4:
993 *(newp++)= *oldp++;
994 *(newp++)= *oldp++;
995 *(newp++)= *oldp++;
996 *(newp++)= *oldp++;
997 break;
998 default:
999 memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize);
1000 newp += tailsize;
1001 }
1002 *newp= NULL;
1003 return(newset);
1004 } /* setnew_delnthsorted */
1005
1006
1007 /*-<a href="qh-set.htm#TOC"
1008 >-------------------------------<a name="setprint">-</a>
1009
1010 qh_setprint( fp, string, set )
1011 print set elements to fp with identifying string
1012
1013 notes:
1014 never errors
1015 */
1016 void qh_setprint(FILE *fp, char* string, setT *set) {
1017 int size, k;
1018
1019 if (!set)
1020 fprintf (fp, "%s set is null\n", string);
1021 else {
1022 SETreturnsize_(set, size);
1023 fprintf (fp, "%s set=%p maxsize=%d size=%d elems=",
1024 string, set, set->maxsize, size);
1025 if (size > set->maxsize)
1026 size= set->maxsize+1;
1027 for (k=0; k < size; k++)
1028 fprintf(fp, " %p", set->e[k].p);
1029 fprintf(fp, "\n");
1030 }
1031 } /* setprint */
1032
1033 /*-<a href="qh-set.htm#TOC"
1034 >-------------------------------<a name="setreplace">-</a>
1035
1036 qh_setreplace( set, oldelem, newelem )
1037 replaces oldelem in set with newelem
1038
1039 notes:
1040 errors if oldelem not in the set
1041 newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
1042
1043 design:
1044 find oldelem
1045 replace with newelem
1046 */
1047 void qh_setreplace(setT *set, void *oldelem, void *newelem) {
1048 void **elemp;
1049
1050 elemp= SETaddr_(set, void);
1051 while(*elemp != oldelem && *elemp)
1052 elemp++;
1053 if (*elemp)
1054 *elemp= newelem;
1055 else {
1056 fprintf (qhmem.ferr, "qhull internal error (qh_setreplace): elem %p not found in set\n",
1057 oldelem);
1058 qh_setprint (qhmem.ferr, "", set);
1059 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1060 }
1061 } /* setreplace */
1062
1063
1064 /*-<a href="qh-set.htm#TOC"
1065 >-------------------------------<a name="setsize">-</a>
1066
1067 qh_setsize( set )
1068 returns the size of a set
1069
1070 notes:
1071 errors if set's maxsize is incorrect
1072 same as SETreturnsize\_(set)
1073
1074 design:
1075 determine actual size of set from maxsize
1076 */
1077 int qh_setsize(setT *set) {
1078 int size, *sizep;
1079
1080 if (!set)
1081 return (0);
1082 sizep= SETsizeaddr_(set);
1083 if ((size= *sizep)) {
1084 size--;
1085 if (size > set->maxsize) {
1086 fprintf (qhmem.ferr, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
1087 size, set->maxsize);
1088 qh_setprint (qhmem.ferr, "set: ", set);
1089 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1090 }
1091 }else
1092 size= set->maxsize;
1093 return size;
1094 } /* setsize */
1095
1096 /*-<a href="qh-set.htm#TOC"
1097 >-------------------------------<a name="settemp">-</a>
1098
1099 qh_settemp( setsize )
1100 return a stacked, temporary set of upto setsize elements
1101
1102 notes:
1103 please use settempfree or settempfree_all to release from qhmem.tempstack
1104 see also qh_setnew
1105
1106 design:
1107 allocate set
1108 append to qhmem.tempstack
1109
1110 */
1111 setT *qh_settemp(int setsize) {
1112 setT *newset;
1113
1114 newset= qh_setnew (setsize);
1115 qh_setappend ((setT **)&qhmem.tempstack, newset);
1116 if (qhmem.IStracing >= 5)
1117 fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n",
1118 newset, newset->maxsize, qh_setsize ((setT*)qhmem.tempstack));
1119 return newset;
1120 } /* settemp */
1121
1122 /*-<a href="qh-set.htm#TOC"
1123 >-------------------------------<a name="settempfree">-</a>
1124
1125 qh_settempfree( set )
1126 free temporary set at top of qhmem.tempstack
1127
1128 notes:
1129 nop if set is NULL
1130 errors if set not from previous qh_settemp
1131
1132 to locate errors:
1133 please use 'T2' to find source and then find mis-matching qh_settemp
1134
1135 design:
1136 check top of qhmem.tempstack
1137 free it
1138 */
1139 void qh_settempfree(setT **set) {
1140 setT *stackedset;
1141
1142 if (!*set)
1143 return;
1144 stackedset= qh_settemppop ();
1145 if (stackedset != *set) {
1146 qh_settemppush(stackedset);
1147 fprintf (qhmem.ferr, "qhull internal error (qh_settempfree): set %p (size %d) was not last temporary allocated (depth %d, set %p, size %d)\n",
1148 *set, qh_setsize(*set), qh_setsize((setT*)qhmem.tempstack)+1,
1149 stackedset, qh_setsize(stackedset));
1150 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1151 }
1152 qh_setfree (set);
1153 } /* settempfree */
1154
1155 /*-<a href="qh-set.htm#TOC"
1156 >-------------------------------<a name="settempfree_all">-</a>
1157
1158 qh_settempfree_all( )
1159 free all temporary sets in qhmem.tempstack
1160
1161 design:
1162 for each set in tempstack
1163 free set
1164 free qhmem.tempstack
1165 */
1166 void qh_settempfree_all(void) {
1167 setT *set, **setp;
1168
1169 FOREACHset_((setT *)qhmem.tempstack)
1170 qh_setfree(&set);
1171 qh_setfree((setT **)&qhmem.tempstack);
1172 } /* settempfree_all */
1173
1174 /*-<a href="qh-set.htm#TOC"
1175 >-------------------------------<a name="settemppop">-</a>
1176
1177 qh_settemppop( )
1178 pop and return temporary set from qhmem.tempstack
1179
1180 notes:
1181 the returned set is permanent
1182
1183 design:
1184 pop and check top of qhmem.tempstack
1185 */
1186 setT *qh_settemppop(void) {
1187 setT *stackedset;
1188
1189 stackedset= (setT*)qh_setdellast((setT *)qhmem.tempstack);
1190 if (!stackedset) {
1191 fprintf (qhmem.ferr, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
1192 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1193 }
1194 if (qhmem.IStracing >= 5)
1195 fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n",
1196 qh_setsize((setT*)qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
1197 return stackedset;
1198 } /* settemppop */
1199
1200 /*-<a href="qh-set.htm#TOC"
1201 >-------------------------------<a name="settemppush">-</a>
1202
1203 qh_settemppush( set )
1204 push temporary set unto qhmem.tempstack (makes it temporary)
1205
1206 notes:
1207 duplicates settemp() for tracing
1208
1209 design:
1210 append set to tempstack
1211 */
1212 void qh_settemppush(setT *set) {
1213
1214 qh_setappend ((setT**)&qhmem.tempstack, set);
1215 if (qhmem.IStracing >= 5)
1216 fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n",
1217 qh_setsize((setT*)qhmem.tempstack), set, qh_setsize(set));
1218 } /* settemppush */
1219
1220
1221 /*-<a href="qh-set.htm#TOC"
1222 >-------------------------------<a name="settruncate">-</a>
1223
1224 qh_settruncate( set, size )
1225 truncate set to size elements
1226
1227 notes:
1228 set must be defined
1229
1230 see:
1231 SETtruncate_
1232
1233 design:
1234 check size
1235 update actual size of set
1236 */
1237 void qh_settruncate (setT *set, int size) {
1238
1239 if (size < 0 || size > set->maxsize) {
1240 fprintf (qhmem.ferr, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
1241 qh_setprint (qhmem.ferr, "", set);
1242 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1243 }
1244 set->e[set->maxsize].i= size+1; /* maybe overwritten */
1245 set->e[size].p= NULL;
1246 } /* settruncate */
1247
1248 /*-<a href="qh-set.htm#TOC"
1249 >-------------------------------<a name="setunique">-</a>
1250
1251 qh_setunique( set, elem )
1252 add elem to unsorted set unless it is already in set
1253
1254 notes:
1255 returns 1 if it is appended
1256
1257 design:
1258 if elem not in set
1259 append elem to set
1260 */
1261 int qh_setunique (setT **set, void *elem) {
1262
1263 if (!qh_setin (*set, elem)) {
1264 qh_setappend (set, elem);
1265 return 1;
1266 }
1267 return 0;
1268 } /* setunique */
1269
1270 /*-<a href="qh-set.htm#TOC"
1271 >-------------------------------<a name="setzero">-</a>
1272
1273 qh_setzero( set, index, size )
1274 zero elements from index on
1275 set actual size of set to size
1276
1277 notes:
1278 set must be defined
1279 the set becomes an indexed set (can not use FOREACH...)
1280
1281 see also:
1282 qh_settruncate
1283
1284 design:
1285 check index and size
1286 update actual size
1287 zero elements starting at e[index]
1288 */
1289 void qh_setzero (setT *set, int index, int size) {
1290 int count;
1291
1292 if (index < 0 || index >= size || size > set->maxsize) {
1293 fprintf (qhmem.ferr, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", index, size);
1294 qh_setprint (qhmem.ferr, "", set);
1295 qh_errexit (qhmem_ERRqhull, NULL, NULL);
1296 }
1297 set->e[set->maxsize].i= size+1; /* may be overwritten */
1298 count= size - index + 1; /* +1 for NULL terminator */
1299 memset ((char *)SETelemaddr_(set, index, void), 0, count * SETelemsize);
1300 } /* setzero */
1301
1302