qset_r.c 35 KB

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