priorityq.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. ** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
  3. ** Copyright (C) [dates of first publication] Silicon Graphics, Inc.
  4. ** All Rights Reserved.
  5. **
  6. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  7. ** of this software and associated documentation files (the "Software"), to deal
  8. ** in the Software without restriction, including without limitation the rights
  9. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  10. ** of the Software, and to permit persons to whom the Software is furnished to do so,
  11. ** subject to the following conditions:
  12. **
  13. ** The above copyright notice including the dates of first publication and either this
  14. ** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
  15. ** included in all copies or substantial portions of the Software.
  16. **
  17. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  18. ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  19. ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC.
  20. ** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  22. ** OR OTHER DEALINGS IN THE SOFTWARE.
  23. **
  24. ** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
  25. ** be used in advertising or otherwise to promote the sale, use or other dealings in
  26. ** this Software without prior written authorization from Silicon Graphics, Inc.
  27. */
  28. /*
  29. ** Author: Eric Veach, July 1994.
  30. */
  31. //#include "tesos.h"
  32. #include <stddef.h>
  33. #include <assert.h>
  34. #include "tesselator.h"
  35. #include "priorityq.h"
  36. #define INIT_SIZE 32
  37. #define TRUE 1
  38. #define FALSE 0
  39. #ifdef FOR_TRITE_TEST_PROGRAM
  40. #define LEQ(x,y) (*pq->leq)(x,y)
  41. #else
  42. /* Violates modularity, but a little faster */
  43. #include "geom.h"
  44. #define LEQ(x,y) VertLeq((TESSvertex *)x, (TESSvertex *)y)
  45. #endif
  46. /* Include all the code for the regular heap-based queue here. */
  47. /* The basic operations are insertion of a new key (pqInsert),
  48. * and examination/extraction of a key whose value is minimum
  49. * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
  50. * for this purpose pqInsert returns a "handle" which is supplied
  51. * as the argument.
  52. *
  53. * An initial heap may be created efficiently by calling pqInsert
  54. * repeatedly, then calling pqInit. In any case pqInit must be called
  55. * before any operations other than pqInsert are used.
  56. *
  57. * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
  58. * This may also be tested with pqIsEmpty.
  59. */
  60. /* Since we support deletion the data structure is a little more
  61. * complicated than an ordinary heap. "nodes" is the heap itself;
  62. * active nodes are stored in the range 1..pq->size. When the
  63. * heap exceeds its allocated size (pq->max), its size doubles.
  64. * The children of node i are nodes 2i and 2i+1.
  65. *
  66. * Each node stores an index into an array "handles". Each handle
  67. * stores a key, plus a pointer back to the node which currently
  68. * represents that key (ie. nodes[handles[i].node].handle == i).
  69. */
  70. #define pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key)
  71. #define pqHeapIsEmpty(pq) ((pq)->size == 0)
  72. /* really pqHeapNewPriorityQHeap */
  73. PriorityQHeap *pqHeapNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) )
  74. {
  75. PriorityQHeap *pq = (PriorityQHeap *)alloc->memalloc( alloc->userData, sizeof( PriorityQHeap ));
  76. if (pq == NULL) return NULL;
  77. pq->size = 0;
  78. pq->max = size;
  79. pq->nodes = (PQnode *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->nodes[0]) );
  80. if (pq->nodes == NULL) {
  81. alloc->memfree( alloc->userData, pq );
  82. return NULL;
  83. }
  84. pq->handles = (PQhandleElem *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->handles[0]) );
  85. if (pq->handles == NULL) {
  86. alloc->memfree( alloc->userData, pq->nodes );
  87. alloc->memfree( alloc->userData, pq );
  88. return NULL;
  89. }
  90. pq->initialized = FALSE;
  91. pq->freeList = 0;
  92. pq->leq = leq;
  93. pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */
  94. pq->handles[1].key = NULL;
  95. return pq;
  96. }
  97. /* really pqHeapDeletePriorityQHeap */
  98. void pqHeapDeletePriorityQ( TESSalloc* alloc, PriorityQHeap *pq )
  99. {
  100. alloc->memfree( alloc->userData, pq->handles );
  101. alloc->memfree( alloc->userData, pq->nodes );
  102. alloc->memfree( alloc->userData, pq );
  103. }
  104. static void FloatDown( PriorityQHeap *pq, int curr )
  105. {
  106. PQnode *n = pq->nodes;
  107. PQhandleElem *h = pq->handles;
  108. PQhandle hCurr, hChild;
  109. int child;
  110. hCurr = n[curr].handle;
  111. for( ;; ) {
  112. child = curr << 1;
  113. if( child < pq->size && LEQ( h[n[child+1].handle].key,
  114. h[n[child].handle].key )) {
  115. ++child;
  116. }
  117. assert(child <= pq->max);
  118. hChild = n[child].handle;
  119. if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) {
  120. n[curr].handle = hCurr;
  121. h[hCurr].node = curr;
  122. break;
  123. }
  124. n[curr].handle = hChild;
  125. h[hChild].node = curr;
  126. curr = child;
  127. }
  128. }
  129. static void FloatUp( PriorityQHeap *pq, int curr )
  130. {
  131. PQnode *n = pq->nodes;
  132. PQhandleElem *h = pq->handles;
  133. PQhandle hCurr, hParent;
  134. int parent;
  135. hCurr = n[curr].handle;
  136. for( ;; ) {
  137. parent = curr >> 1;
  138. hParent = n[parent].handle;
  139. if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) {
  140. n[curr].handle = hCurr;
  141. h[hCurr].node = curr;
  142. break;
  143. }
  144. n[curr].handle = hParent;
  145. h[hParent].node = curr;
  146. curr = parent;
  147. }
  148. }
  149. /* really pqHeapInit */
  150. void pqHeapInit( PriorityQHeap *pq )
  151. {
  152. int i;
  153. /* This method of building a heap is O(n), rather than O(n lg n). */
  154. for( i = pq->size; i >= 1; --i ) {
  155. FloatDown( pq, i );
  156. }
  157. pq->initialized = TRUE;
  158. }
  159. /* really pqHeapInsert */
  160. /* returns INV_HANDLE iff out of memory */
  161. PQhandle pqHeapInsert( TESSalloc* alloc, PriorityQHeap *pq, PQkey keyNew )
  162. {
  163. int curr;
  164. PQhandle free;
  165. curr = ++ pq->size;
  166. if( (curr*2) > pq->max ) {
  167. if (!alloc->memrealloc)
  168. {
  169. return INV_HANDLE;
  170. }
  171. else
  172. {
  173. PQnode *saveNodes= pq->nodes;
  174. PQhandleElem *saveHandles= pq->handles;
  175. // If the heap overflows, double its size.
  176. pq->max <<= 1;
  177. pq->nodes = (PQnode *)alloc->memrealloc( alloc->userData, pq->nodes,
  178. (size_t)((pq->max + 1) * sizeof( pq->nodes[0] )));
  179. if (pq->nodes == NULL) {
  180. pq->nodes = saveNodes; // restore ptr to free upon return
  181. return INV_HANDLE;
  182. }
  183. pq->handles = (PQhandleElem *)alloc->memrealloc( alloc->userData, pq->handles,
  184. (size_t) ((pq->max + 1) * sizeof( pq->handles[0] )));
  185. if (pq->handles == NULL) {
  186. pq->handles = saveHandles; // restore ptr to free upon return
  187. return INV_HANDLE;
  188. }
  189. }
  190. }
  191. if( pq->freeList == 0 ) {
  192. free = curr;
  193. } else {
  194. free = pq->freeList;
  195. pq->freeList = pq->handles[free].node;
  196. }
  197. pq->nodes[curr].handle = free;
  198. pq->handles[free].node = curr;
  199. pq->handles[free].key = keyNew;
  200. if( pq->initialized ) {
  201. FloatUp( pq, curr );
  202. }
  203. assert(free != INV_HANDLE);
  204. return free;
  205. }
  206. /* really pqHeapExtractMin */
  207. PQkey pqHeapExtractMin( PriorityQHeap *pq )
  208. {
  209. PQnode *n = pq->nodes;
  210. PQhandleElem *h = pq->handles;
  211. PQhandle hMin = n[1].handle;
  212. PQkey min = h[hMin].key;
  213. if( pq->size > 0 ) {
  214. n[1].handle = n[pq->size].handle;
  215. h[n[1].handle].node = 1;
  216. h[hMin].key = NULL;
  217. h[hMin].node = pq->freeList;
  218. pq->freeList = hMin;
  219. if( -- pq->size > 0 ) {
  220. FloatDown( pq, 1 );
  221. }
  222. }
  223. return min;
  224. }
  225. /* really pqHeapDelete */
  226. void pqHeapDelete( PriorityQHeap *pq, PQhandle hCurr )
  227. {
  228. PQnode *n = pq->nodes;
  229. PQhandleElem *h = pq->handles;
  230. int curr;
  231. assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL );
  232. curr = h[hCurr].node;
  233. n[curr].handle = n[pq->size].handle;
  234. h[n[curr].handle].node = curr;
  235. if( curr <= -- pq->size ) {
  236. if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) {
  237. FloatDown( pq, curr );
  238. } else {
  239. FloatUp( pq, curr );
  240. }
  241. }
  242. h[hCurr].key = NULL;
  243. h[hCurr].node = pq->freeList;
  244. pq->freeList = hCurr;
  245. }
  246. /* Now redefine all the function names to map to their "Sort" versions. */
  247. /* really tessPqSortNewPriorityQ */
  248. PriorityQ *pqNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) )
  249. {
  250. PriorityQ *pq = (PriorityQ *)alloc->memalloc( alloc->userData, sizeof( PriorityQ ));
  251. if (pq == NULL) return NULL;
  252. pq->heap = pqHeapNewPriorityQ( alloc, size, leq );
  253. if (pq->heap == NULL) {
  254. alloc->memfree( alloc->userData, pq );
  255. return NULL;
  256. }
  257. // pq->keys = (PQkey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) );
  258. pq->keys = (PQkey *)alloc->memalloc( alloc->userData, size * sizeof(pq->keys[0]) );
  259. if (pq->keys == NULL) {
  260. pqHeapDeletePriorityQ( alloc, pq->heap );
  261. alloc->memfree( alloc->userData, pq );
  262. return NULL;
  263. }
  264. pq->size = 0;
  265. pq->max = size; //INIT_SIZE;
  266. pq->initialized = FALSE;
  267. pq->leq = leq;
  268. return pq;
  269. }
  270. /* really tessPqSortDeletePriorityQ */
  271. void pqDeletePriorityQ( TESSalloc* alloc, PriorityQ *pq )
  272. {
  273. assert(pq != NULL);
  274. if (pq->heap != NULL) pqHeapDeletePriorityQ( alloc, pq->heap );
  275. if (pq->order != NULL) alloc->memfree( alloc->userData, pq->order );
  276. if (pq->keys != NULL) alloc->memfree( alloc->userData, pq->keys );
  277. alloc->memfree( alloc->userData, pq );
  278. }
  279. #define LT(x,y) (! LEQ(y,x))
  280. #define GT(x,y) (! LEQ(x,y))
  281. #define Swap(a,b) if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else
  282. /* really tessPqSortInit */
  283. int pqInit( TESSalloc* alloc, PriorityQ *pq )
  284. {
  285. PQkey **p, **r, **i, **j, *piv;
  286. struct { PQkey **p, **r; } Stack[50], *top = Stack;
  287. unsigned int seed = 2016473283;
  288. /* Create an array of indirect pointers to the keys, so that we
  289. * the handles we have returned are still valid.
  290. */
  291. /*
  292. pq->order = (PQkey **)memAlloc( (size_t)
  293. (pq->size * sizeof(pq->order[0])) );
  294. */
  295. pq->order = (PQkey **)alloc->memalloc( alloc->userData,
  296. (size_t)((pq->size+1) * sizeof(pq->order[0])) );
  297. /* the previous line is a patch to compensate for the fact that IBM */
  298. /* machines return a null on a malloc of zero bytes (unlike SGI), */
  299. /* so we have to put in this defense to guard against a memory */
  300. /* fault four lines down. from [email protected]. */
  301. if (pq->order == NULL) return 0;
  302. p = pq->order;
  303. r = p + pq->size - 1;
  304. for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) {
  305. *i = piv;
  306. }
  307. /* Sort the indirect pointers in descending order,
  308. * using randomized Quicksort
  309. */
  310. top->p = p; top->r = r; ++top;
  311. while( --top >= Stack ) {
  312. p = top->p;
  313. r = top->r;
  314. while( r > p + 10 ) {
  315. seed = seed * 1539415821 + 1;
  316. i = p + seed % (r - p + 1);
  317. piv = *i;
  318. *i = *p;
  319. *p = piv;
  320. i = p - 1;
  321. j = r + 1;
  322. do {
  323. do { ++i; } while( GT( **i, *piv ));
  324. do { --j; } while( LT( **j, *piv ));
  325. Swap( i, j );
  326. } while( i < j );
  327. Swap( i, j ); /* Undo last swap */
  328. if( i - p < r - j ) {
  329. top->p = j+1; top->r = r; ++top;
  330. r = i-1;
  331. } else {
  332. top->p = p; top->r = i-1; ++top;
  333. p = j+1;
  334. }
  335. }
  336. /* Insertion sort small lists */
  337. for( i = p+1; i <= r; ++i ) {
  338. piv = *i;
  339. for( j = i; j > p && LT( **(j-1), *piv ); --j ) {
  340. *j = *(j-1);
  341. }
  342. *j = piv;
  343. }
  344. }
  345. pq->max = pq->size;
  346. pq->initialized = TRUE;
  347. pqHeapInit( pq->heap ); /* always succeeds */
  348. #ifndef NDEBUG
  349. p = pq->order;
  350. r = p + pq->size - 1;
  351. for( i = p; i < r; ++i ) {
  352. assert( LEQ( **(i+1), **i ));
  353. }
  354. #endif
  355. return 1;
  356. }
  357. /* really tessPqSortInsert */
  358. /* returns INV_HANDLE iff out of memory */
  359. PQhandle pqInsert( TESSalloc* alloc, PriorityQ *pq, PQkey keyNew )
  360. {
  361. int curr;
  362. if( pq->initialized ) {
  363. return pqHeapInsert( alloc, pq->heap, keyNew );
  364. }
  365. curr = pq->size;
  366. if( ++ pq->size >= pq->max ) {
  367. if (!alloc->memrealloc)
  368. {
  369. return INV_HANDLE;
  370. }
  371. else
  372. {
  373. PQkey *saveKey= pq->keys;
  374. // If the heap overflows, double its size.
  375. pq->max <<= 1;
  376. pq->keys = (PQkey *)alloc->memrealloc( alloc->userData, pq->keys,
  377. (size_t)(pq->max * sizeof( pq->keys[0] )));
  378. if (pq->keys == NULL) {
  379. pq->keys = saveKey; // restore ptr to free upon return
  380. return INV_HANDLE;
  381. }
  382. }
  383. }
  384. assert(curr != INV_HANDLE);
  385. pq->keys[curr] = keyNew;
  386. /* Negative handles index the sorted array. */
  387. return -(curr+1);
  388. }
  389. /* really tessPqSortExtractMin */
  390. PQkey pqExtractMin( PriorityQ *pq )
  391. {
  392. PQkey sortMin, heapMin;
  393. if( pq->size == 0 ) {
  394. return pqHeapExtractMin( pq->heap );
  395. }
  396. sortMin = *(pq->order[pq->size-1]);
  397. if( ! pqHeapIsEmpty( pq->heap )) {
  398. heapMin = pqHeapMinimum( pq->heap );
  399. if( LEQ( heapMin, sortMin )) {
  400. return pqHeapExtractMin( pq->heap );
  401. }
  402. }
  403. do {
  404. -- pq->size;
  405. } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL );
  406. return sortMin;
  407. }
  408. /* really tessPqSortMinimum */
  409. PQkey pqMinimum( PriorityQ *pq )
  410. {
  411. PQkey sortMin, heapMin;
  412. if( pq->size == 0 ) {
  413. return pqHeapMinimum( pq->heap );
  414. }
  415. sortMin = *(pq->order[pq->size-1]);
  416. if( ! pqHeapIsEmpty( pq->heap )) {
  417. heapMin = pqHeapMinimum( pq->heap );
  418. if( LEQ( heapMin, sortMin )) {
  419. return heapMin;
  420. }
  421. }
  422. return sortMin;
  423. }
  424. /* really tessPqSortIsEmpty */
  425. int pqIsEmpty( PriorityQ *pq )
  426. {
  427. return (pq->size == 0) && pqHeapIsEmpty( pq->heap );
  428. }
  429. /* really tessPqSortDelete */
  430. void pqDelete( PriorityQ *pq, PQhandle curr )
  431. {
  432. if( curr >= 0 ) {
  433. pqHeapDelete( pq->heap, curr );
  434. return;
  435. }
  436. curr = -(curr+1);
  437. assert( curr < pq->max && pq->keys[curr] != NULL );
  438. pq->keys[curr] = NULL;
  439. while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) {
  440. -- pq->size;
  441. }
  442. }