QuantHeap.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * heap data type used by the image quantizer
  6. *
  7. * history:
  8. * 98-09-10 tjs Contributed
  9. * 98-12-29 fl Added to PIL 1.0b1
  10. *
  11. * Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
  12. *
  13. * Copyright (c) 1998 by Toby J Sargeant
  14. * Copyright (c) 1998 by Secret Labs AB
  15. *
  16. * See the README file for information on usage and redistribution.
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <math.h>
  22. #include <limits.h>
  23. #include "QuantHeap.h"
  24. struct _Heap {
  25. void **heap;
  26. unsigned int heapsize;
  27. unsigned int heapcount;
  28. HeapCmpFunc cf;
  29. };
  30. #define INITIAL_SIZE 256
  31. // #define DEBUG
  32. #ifdef DEBUG
  33. static int
  34. _heap_test(Heap *);
  35. #endif
  36. void
  37. ImagingQuantHeapFree(Heap *h) {
  38. free(h->heap);
  39. free(h);
  40. }
  41. static int
  42. _heap_grow(Heap *h, unsigned int newsize) {
  43. void *newheap;
  44. if (!newsize) {
  45. newsize = h->heapsize << 1;
  46. }
  47. if (newsize < h->heapsize) {
  48. return 0;
  49. }
  50. if (newsize > INT_MAX / sizeof(void *)) {
  51. return 0;
  52. }
  53. /* malloc check ok, using calloc for overflow, also checking
  54. above due to memcpy below*/
  55. newheap = calloc(newsize, sizeof(void *));
  56. if (!newheap) {
  57. return 0;
  58. }
  59. memcpy(newheap, h->heap, sizeof(void *) * h->heapsize);
  60. free(h->heap);
  61. h->heap = newheap;
  62. h->heapsize = newsize;
  63. return 1;
  64. }
  65. #ifdef DEBUG
  66. static int
  67. _heap_test(Heap *h) {
  68. unsigned int k;
  69. for (k = 1; k * 2 <= h->heapcount; k++) {
  70. if (h->cf(h, h->heap[k], h->heap[k * 2]) < 0) {
  71. printf("heap is bad\n");
  72. return 0;
  73. }
  74. if (k * 2 + 1 <= h->heapcount && h->cf(h, h->heap[k], h->heap[k * 2 + 1]) < 0) {
  75. printf("heap is bad\n");
  76. return 0;
  77. }
  78. }
  79. return 1;
  80. }
  81. #endif
  82. int
  83. ImagingQuantHeapRemove(Heap *h, void **r) {
  84. unsigned int k, l;
  85. void *v;
  86. if (!h->heapcount) {
  87. return 0;
  88. }
  89. *r = h->heap[1];
  90. v = h->heap[h->heapcount--];
  91. for (k = 1; k * 2 <= h->heapcount; k = l) {
  92. l = k * 2;
  93. if (l < h->heapcount) {
  94. if (h->cf(h, h->heap[l], h->heap[l + 1]) < 0) {
  95. l++;
  96. }
  97. }
  98. if (h->cf(h, v, h->heap[l]) > 0) {
  99. break;
  100. }
  101. h->heap[k] = h->heap[l];
  102. }
  103. h->heap[k] = v;
  104. #ifdef DEBUG
  105. if (!_heap_test(h)) {
  106. printf("oops - heap_remove messed up the heap\n");
  107. exit(1);
  108. }
  109. #endif
  110. return 1;
  111. }
  112. int
  113. ImagingQuantHeapAdd(Heap *h, void *val) {
  114. int k;
  115. if (h->heapcount == h->heapsize - 1) {
  116. _heap_grow(h, 0);
  117. }
  118. k = ++h->heapcount;
  119. while (k != 1) {
  120. if (h->cf(h, val, h->heap[k / 2]) <= 0) {
  121. break;
  122. }
  123. h->heap[k] = h->heap[k / 2];
  124. k >>= 1;
  125. }
  126. h->heap[k] = val;
  127. #ifdef DEBUG
  128. if (!_heap_test(h)) {
  129. printf("oops - heap_add messed up the heap\n");
  130. exit(1);
  131. }
  132. #endif
  133. return 1;
  134. }
  135. int
  136. ImagingQuantHeapTop(Heap *h, void **r) {
  137. if (!h->heapcount) {
  138. return 0;
  139. }
  140. *r = h->heap[1];
  141. return 1;
  142. }
  143. Heap *
  144. ImagingQuantHeapNew(HeapCmpFunc cf) {
  145. Heap *h;
  146. /* malloc check ok, small constant allocation */
  147. h = malloc(sizeof(Heap));
  148. if (!h) {
  149. return NULL;
  150. }
  151. h->heapsize = INITIAL_SIZE;
  152. /* malloc check ok, using calloc for overflow */
  153. h->heap = calloc(h->heapsize, sizeof(void *));
  154. if (!h->heap) {
  155. free(h);
  156. return NULL;
  157. }
  158. h->heapcount = 0;
  159. h->cf = cf;
  160. return h;
  161. }