LCOV - code coverage report
Current view: top level - alg/internal_libqhull - qset_r.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 290 480 60.4 %
Date: 2024-11-21 22:18:42 Functions: 29 39 74.4 %

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

Generated by: LCOV version 1.14