mem_r.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*<html><pre> -<a href="qh-mem_r.htm"
  2. >-------------------------------</a><a name="TOP">-</a>
  3. mem_r.c
  4. memory management routines for qhull
  5. See libqhull/mem.c for a standalone program.
  6. To initialize memory:
  7. qh_meminit(qh, stderr);
  8. qh_meminitbuffers(qh, qh->IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
  9. qh_memsize(qh, (int)sizeof(facetT));
  10. qh_memsize(qh, (int)sizeof(facetT));
  11. ...
  12. qh_memsetup(qh);
  13. To free up all memory buffers:
  14. qh_memfreeshort(qh, &curlong, &totlong);
  15. if qh_NOmem,
  16. malloc/free is used instead of mem_r.c
  17. notes:
  18. uses Quickfit algorithm (freelists for commonly allocated sizes)
  19. assumes small sizes for freelists (it discards the tail of memory buffers)
  20. see:
  21. qh-mem_r.htm and mem_r.h
  22. global_r.c (qh_initbuffers) for an example of using mem_r.c
  23. Copyright (c) 1993-2020 The Geometry Center.
  24. $Id: //main/2019/qhull/src/libqhull_r/mem_r.c#7 $$Change: 2953 $
  25. $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
  26. */
  27. #include "libqhull_r.h" /* includes user_r.h and mem_r.h */
  28. #include <string.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #ifndef qh_NOmem
  32. /*============= internal functions ==============*/
  33. static int qh_intcompare(const void *i, const void *j);
  34. /*========== functions in alphabetical order ======== */
  35. /*-<a href="qh-mem_r.htm#TOC"
  36. >-------------------------------</a><a name="intcompare">-</a>
  37. qh_intcompare( i, j )
  38. used by qsort and bsearch to compare two integers
  39. */
  40. static int qh_intcompare(const void *i, const void *j) {
  41. return(*((const int *)i) - *((const int *)j));
  42. } /* intcompare */
  43. /*-<a href="qh-mem_r.htm#TOC"
  44. >--------------------------------</a><a name="memalloc">-</a>
  45. qh_memalloc(qh, insize )
  46. returns object of insize bytes
  47. qhmem is the global memory structure
  48. returns:
  49. pointer to allocated memory
  50. errors if insufficient memory
  51. notes:
  52. use explicit type conversion to avoid type warnings on some compilers
  53. actual object may be larger than insize
  54. use qh_memalloc_() for inline code for quick allocations
  55. logs allocations if 'T5'
  56. caller is responsible for freeing the memory.
  57. short memory is freed on shutdown by qh_memfreeshort unless qh_NOmem
  58. design:
  59. if size < qh->qhmem.LASTsize
  60. if qh->qhmem.freelists[size] non-empty
  61. return first object on freelist
  62. else
  63. round up request to size of qh->qhmem.freelists[size]
  64. allocate new allocation buffer if necessary
  65. allocate object from allocation buffer
  66. else
  67. allocate object with qh_malloc() in user_r.c
  68. */
  69. void *qh_memalloc(qhT *qh, int insize) {
  70. void **freelistp, *newbuffer;
  71. int idx, size, n;
  72. int outsize, bufsize;
  73. void *object;
  74. if (insize<0) {
  75. qh_fprintf(qh, qh->qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d). Did int overflow due to high-D?\n", insize); /* WARN64 */
  76. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  77. }
  78. if (insize>=0 && insize <= qh->qhmem.LASTsize) {
  79. idx= qh->qhmem.indextable[insize];
  80. outsize= qh->qhmem.sizetable[idx];
  81. qh->qhmem.totshort += outsize;
  82. freelistp= qh->qhmem.freelists+idx;
  83. if ((object= *freelistp)) {
  84. qh->qhmem.cntquick++;
  85. qh->qhmem.totfree -= outsize;
  86. *freelistp= *((void **)*freelistp); /* replace freelist with next object */
  87. #ifdef qh_TRACEshort
  88. n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
  89. if (qh->qhmem.IStracing >= 5)
  90. qh_fprintf(qh, qh->qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
  91. #endif
  92. return(object);
  93. }else {
  94. qh->qhmem.cntshort++;
  95. if (outsize > qh->qhmem.freesize) {
  96. qh->qhmem.totdropped += qh->qhmem.freesize;
  97. if (!qh->qhmem.curbuffer)
  98. bufsize= qh->qhmem.BUFinit;
  99. else
  100. bufsize= qh->qhmem.BUFsize;
  101. if (!(newbuffer= qh_malloc((size_t)bufsize))) {
  102. qh_fprintf(qh, qh->qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
  103. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  104. }
  105. *((void **)newbuffer)= qh->qhmem.curbuffer; /* prepend newbuffer to curbuffer
  106. list. newbuffer!=0 by QH6080 */
  107. qh->qhmem.curbuffer= newbuffer;
  108. size= ((int)sizeof(void **) + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
  109. qh->qhmem.freemem= (void *)((char *)newbuffer+size);
  110. qh->qhmem.freesize= bufsize - size;
  111. qh->qhmem.totbuffer += bufsize - size; /* easier to check */
  112. /* Periodically test totbuffer. It matches at beginning and exit of every call */
  113. n= qh->qhmem.totshort + qh->qhmem.totfree + qh->qhmem.totdropped + qh->qhmem.freesize - outsize;
  114. if (qh->qhmem.totbuffer != n) {
  115. qh_fprintf(qh, qh->qhmem.ferr, 6212, "qhull internal error (qh_memalloc): short totbuffer %d != totshort+totfree... %d\n", qh->qhmem.totbuffer, n);
  116. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  117. }
  118. }
  119. object= qh->qhmem.freemem;
  120. qh->qhmem.freemem= (void *)((char *)qh->qhmem.freemem + outsize);
  121. qh->qhmem.freesize -= outsize;
  122. qh->qhmem.totunused += outsize - insize;
  123. #ifdef qh_TRACEshort
  124. n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
  125. if (qh->qhmem.IStracing >= 5)
  126. qh_fprintf(qh, qh->qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
  127. #endif
  128. return object;
  129. }
  130. }else { /* long allocation */
  131. if (!qh->qhmem.indextable) {
  132. qh_fprintf(qh, qh->qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
  133. qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
  134. }
  135. outsize= insize;
  136. qh->qhmem.cntlong++;
  137. qh->qhmem.totlong += outsize;
  138. if (qh->qhmem.maxlong < qh->qhmem.totlong)
  139. qh->qhmem.maxlong= qh->qhmem.totlong;
  140. if (!(object= qh_malloc((size_t)outsize))) {
  141. qh_fprintf(qh, qh->qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
  142. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  143. }
  144. if (qh->qhmem.IStracing >= 5)
  145. qh_fprintf(qh, qh->qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, outsize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
  146. }
  147. return(object);
  148. } /* memalloc */
  149. /*-<a href="qh-mem_r.htm#TOC"
  150. >--------------------------------</a><a name="memcheck">-</a>
  151. qh_memcheck(qh)
  152. */
  153. void qh_memcheck(qhT *qh) {
  154. int i, count, totfree= 0;
  155. void *object;
  156. if (!qh) {
  157. qh_fprintf_stderr(6243, "qhull internal error (qh_memcheck): qh is 0. It does not point to a qhT\n");
  158. qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
  159. }
  160. if (qh->qhmem.ferr == 0 || qh->qhmem.IStracing < 0 || qh->qhmem.IStracing > 10 || (((qh->qhmem.ALIGNmask+1) & qh->qhmem.ALIGNmask) != 0)) {
  161. qh_fprintf_stderr(6244, "qhull internal error (qh_memcheck): either qh->qhmem is overwritten or qh->qhmem is not initialized. Call qh_meminit or qh_new_qhull before calling qh_mem routines. ferr 0x%x, IsTracing %d, ALIGNmask 0x%x\n",
  162. qh->qhmem.ferr, qh->qhmem.IStracing, qh->qhmem.ALIGNmask);
  163. qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
  164. }
  165. if (qh->qhmem.IStracing != 0)
  166. qh_fprintf(qh, qh->qhmem.ferr, 8143, "qh_memcheck: check size of freelists on qh->qhmem\nqh_memcheck: A segmentation fault indicates an overwrite of qh->qhmem\n");
  167. for (i=0; i < qh->qhmem.TABLEsize; i++) {
  168. count=0;
  169. for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
  170. count++;
  171. totfree += qh->qhmem.sizetable[i] * count;
  172. }
  173. if (totfree != qh->qhmem.totfree) {
  174. qh_fprintf(qh, qh->qhmem.ferr, 6211, "qhull internal error (qh_memcheck): totfree %d not equal to freelist total %d\n", qh->qhmem.totfree, totfree);
  175. qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
  176. }
  177. if (qh->qhmem.IStracing != 0)
  178. qh_fprintf(qh, qh->qhmem.ferr, 8144, "qh_memcheck: total size of freelists totfree is the same as qh->qhmem.totfree\n", totfree);
  179. } /* memcheck */
  180. /*-<a href="qh-mem_r.htm#TOC"
  181. >--------------------------------</a><a name="memfree">-</a>
  182. qh_memfree(qh, object, insize )
  183. free up an object of size bytes
  184. size is insize from qh_memalloc
  185. notes:
  186. object may be NULL
  187. type checking warns if using (void **)object
  188. use qh_memfree_() for quick free's of small objects
  189. design:
  190. if size <= qh->qhmem.LASTsize
  191. append object to corresponding freelist
  192. else
  193. call qh_free(object)
  194. */
  195. void qh_memfree(qhT *qh, void *object, int insize) {
  196. void **freelistp;
  197. int idx, outsize;
  198. if (!object)
  199. return;
  200. if (insize <= qh->qhmem.LASTsize) {
  201. qh->qhmem.freeshort++;
  202. idx= qh->qhmem.indextable[insize];
  203. outsize= qh->qhmem.sizetable[idx];
  204. qh->qhmem.totfree += outsize;
  205. qh->qhmem.totshort -= outsize;
  206. freelistp= qh->qhmem.freelists + idx;
  207. *((void **)object)= *freelistp;
  208. *freelistp= object;
  209. #ifdef qh_TRACEshort
  210. idx= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
  211. if (qh->qhmem.IStracing >= 5)
  212. qh_fprintf(qh, qh->qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
  213. #endif
  214. }else {
  215. qh->qhmem.freelong++;
  216. qh->qhmem.totlong -= insize;
  217. if (qh->qhmem.IStracing >= 5)
  218. qh_fprintf(qh, qh->qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
  219. qh_free(object);
  220. }
  221. } /* memfree */
  222. /*-<a href="qh-mem_r.htm#TOC"
  223. >-------------------------------</a><a name="memfreeshort">-</a>
  224. qh_memfreeshort(qh, curlong, totlong )
  225. frees up all short and qhmem memory allocations
  226. returns:
  227. number and size of current long allocations
  228. notes:
  229. if qh_NOmem (qh_malloc() for all allocations),
  230. short objects (e.g., facetT) are not recovered.
  231. use qh_freeqhull(qh, qh_ALL) instead.
  232. see:
  233. qh_freeqhull(qh, allMem)
  234. qh_memtotal(qh, curlong, totlong, curshort, totshort, maxlong, totbuffer);
  235. */
  236. void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
  237. void *buffer, *nextbuffer;
  238. FILE *ferr;
  239. *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
  240. *totlong= qh->qhmem.totlong;
  241. for (buffer=qh->qhmem.curbuffer; buffer; buffer= nextbuffer) {
  242. nextbuffer= *((void **) buffer);
  243. qh_free(buffer);
  244. }
  245. qh->qhmem.curbuffer= NULL;
  246. if (qh->qhmem.LASTsize) {
  247. qh_free(qh->qhmem.indextable);
  248. qh_free(qh->qhmem.freelists);
  249. qh_free(qh->qhmem.sizetable);
  250. }
  251. ferr= qh->qhmem.ferr;
  252. memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
  253. qh->qhmem.ferr= ferr;
  254. } /* memfreeshort */
  255. /*-<a href="qh-mem_r.htm#TOC"
  256. >--------------------------------</a><a name="meminit">-</a>
  257. qh_meminit(qh, ferr )
  258. initialize qhmem and test sizeof(void *)
  259. Does not throw errors. qh_exit on failure
  260. */
  261. void qh_meminit(qhT *qh, FILE *ferr) {
  262. memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
  263. if (ferr)
  264. qh->qhmem.ferr= ferr;
  265. else
  266. qh->qhmem.ferr= stderr;
  267. if (sizeof(void *) < sizeof(int)) {
  268. qh_fprintf(qh, qh->qhmem.ferr, 6083, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d. qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
  269. qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
  270. }
  271. if (sizeof(void *) > sizeof(ptr_intT)) {
  272. qh_fprintf(qh, qh->qhmem.ferr, 6084, "qhull internal error (qh_meminit): sizeof(void *) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem_r.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
  273. qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
  274. }
  275. qh_memcheck(qh);
  276. } /* meminit */
  277. /*-<a href="qh-mem_r.htm#TOC"
  278. >-------------------------------</a><a name="meminitbuffers">-</a>
  279. qh_meminitbuffers(qh, tracelevel, alignment, numsizes, bufsize, bufinit )
  280. initialize qhmem
  281. if tracelevel >= 5, trace memory allocations
  282. alignment= desired address alignment for memory allocations
  283. numsizes= number of freelists
  284. bufsize= size of additional memory buffers for short allocations
  285. bufinit= size of initial memory buffer for short allocations
  286. */
  287. void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
  288. qh->qhmem.IStracing= tracelevel;
  289. qh->qhmem.NUMsizes= numsizes;
  290. qh->qhmem.BUFsize= bufsize;
  291. qh->qhmem.BUFinit= bufinit;
  292. qh->qhmem.ALIGNmask= alignment-1;
  293. if (qh->qhmem.ALIGNmask & ~qh->qhmem.ALIGNmask) {
  294. qh_fprintf(qh, qh->qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
  295. qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
  296. }
  297. qh->qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
  298. qh->qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
  299. if (!qh->qhmem.sizetable || !qh->qhmem.freelists) {
  300. qh_fprintf(qh, qh->qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
  301. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  302. }
  303. if (qh->qhmem.IStracing >= 1)
  304. qh_fprintf(qh, qh->qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
  305. } /* meminitbuffers */
  306. /*-<a href="qh-mem_r.htm#TOC"
  307. >-------------------------------</a><a name="memsetup">-</a>
  308. qh_memsetup(qh)
  309. set up memory after running memsize()
  310. */
  311. void qh_memsetup(qhT *qh) {
  312. int k,i;
  313. qsort(qh->qhmem.sizetable, (size_t)qh->qhmem.TABLEsize, sizeof(int), qh_intcompare);
  314. qh->qhmem.LASTsize= qh->qhmem.sizetable[qh->qhmem.TABLEsize-1];
  315. if (qh->qhmem.LASTsize >= qh->qhmem.BUFsize || qh->qhmem.LASTsize >= qh->qhmem.BUFinit) {
  316. qh_fprintf(qh, qh->qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
  317. qh->qhmem.LASTsize, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
  318. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  319. }
  320. if (!(qh->qhmem.indextable= (int *)qh_malloc((size_t)(qh->qhmem.LASTsize+1) * sizeof(int)))) {
  321. qh_fprintf(qh, qh->qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
  322. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  323. }
  324. for (k=qh->qhmem.LASTsize+1; k--; )
  325. qh->qhmem.indextable[k]= k;
  326. i= 0;
  327. for (k=0; k <= qh->qhmem.LASTsize; k++) {
  328. if (qh->qhmem.indextable[k] <= qh->qhmem.sizetable[i])
  329. qh->qhmem.indextable[k]= i;
  330. else
  331. qh->qhmem.indextable[k]= ++i;
  332. }
  333. } /* memsetup */
  334. /*-<a href="qh-mem_r.htm#TOC"
  335. >-------------------------------</a><a name="memsize">-</a>
  336. qh_memsize(qh, size )
  337. define a free list for this size
  338. */
  339. void qh_memsize(qhT *qh, int size) {
  340. int k;
  341. if (qh->qhmem.LASTsize) {
  342. qh_fprintf(qh, qh->qhmem.ferr, 6089, "qhull internal error (qh_memsize): qh_memsize called after qh_memsetup\n");
  343. qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
  344. }
  345. size= (size + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
  346. if (qh->qhmem.IStracing >= 3)
  347. qh_fprintf(qh, qh->qhmem.ferr, 3078, "qh_memsize: quick memory of %d bytes\n", size);
  348. for (k=qh->qhmem.TABLEsize; k--; ) {
  349. if (qh->qhmem.sizetable[k] == size)
  350. return;
  351. }
  352. if (qh->qhmem.TABLEsize < qh->qhmem.NUMsizes)
  353. qh->qhmem.sizetable[qh->qhmem.TABLEsize++]= size;
  354. else
  355. qh_fprintf(qh, qh->qhmem.ferr, 7060, "qhull warning (qh_memsize): free list table has room for only %d sizes\n", qh->qhmem.NUMsizes);
  356. } /* memsize */
  357. /*-<a href="qh-mem_r.htm#TOC"
  358. >-------------------------------</a><a name="memstatistics">-</a>
  359. qh_memstatistics(qh, fp )
  360. print out memory statistics
  361. Verifies that qh->qhmem.totfree == sum of freelists
  362. */
  363. void qh_memstatistics(qhT *qh, FILE *fp) {
  364. int i;
  365. int count;
  366. void *object;
  367. qh_memcheck(qh);
  368. qh_fprintf(qh, fp, 9278, "\nmemory statistics:\n\
  369. %7d quick allocations\n\
  370. %7d short allocations\n\
  371. %7d long allocations\n\
  372. %7d short frees\n\
  373. %7d long frees\n\
  374. %7d bytes of short memory in use\n\
  375. %7d bytes of short memory in freelists\n\
  376. %7d bytes of dropped short memory\n\
  377. %7d bytes of unused short memory (estimated)\n\
  378. %7d bytes of long memory allocated (max, except for input)\n\
  379. %7d bytes of long memory in use (in %d pieces)\n\
  380. %7d bytes of short memory buffers (minus links)\n\
  381. %7d bytes per short memory buffer (initially %d bytes)\n",
  382. qh->qhmem.cntquick, qh->qhmem.cntshort, qh->qhmem.cntlong,
  383. qh->qhmem.freeshort, qh->qhmem.freelong,
  384. qh->qhmem.totshort, qh->qhmem.totfree,
  385. qh->qhmem.totdropped + qh->qhmem.freesize, qh->qhmem.totunused,
  386. qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong,
  387. qh->qhmem.totbuffer, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
  388. if (qh->qhmem.cntlarger) {
  389. qh_fprintf(qh, fp, 9279, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
  390. qh->qhmem.cntlarger, ((double)qh->qhmem.totlarger)/(double)qh->qhmem.cntlarger);
  391. qh_fprintf(qh, fp, 9280, " freelists(bytes->count):");
  392. }
  393. for (i=0; i < qh->qhmem.TABLEsize; i++) {
  394. count=0;
  395. for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
  396. count++;
  397. qh_fprintf(qh, fp, 9281, " %d->%d", qh->qhmem.sizetable[i], count);
  398. }
  399. qh_fprintf(qh, fp, 9282, "\n\n");
  400. } /* memstatistics */
  401. /*-<a href="qh-mem_r.htm#TOC"
  402. >-------------------------------</a><a name="NOmem">-</a>
  403. qh_NOmem
  404. turn off quick-fit memory allocation
  405. notes:
  406. uses qh_malloc() and qh_free() instead
  407. */
  408. #else /* qh_NOmem */
  409. void *qh_memalloc(qhT *qh, int insize) {
  410. void *object;
  411. if (!(object= qh_malloc((size_t)insize))) {
  412. qh_fprintf(qh, qh->qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
  413. qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
  414. }
  415. qh->qhmem.cntlong++;
  416. qh->qhmem.totlong += insize;
  417. if (qh->qhmem.maxlong < qh->qhmem.totlong)
  418. qh->qhmem.maxlong= qh->qhmem.totlong;
  419. if (qh->qhmem.IStracing >= 5)
  420. qh_fprintf(qh, qh->qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
  421. return object;
  422. }
  423. void qh_memcheck(qhT *qh) {
  424. }
  425. void qh_memfree(qhT *qh, void *object, int insize) {
  426. if (!object)
  427. return;
  428. qh_free(object);
  429. qh->qhmem.freelong++;
  430. qh->qhmem.totlong -= insize;
  431. if (qh->qhmem.IStracing >= 5)
  432. qh_fprintf(qh, qh->qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
  433. }
  434. void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
  435. *totlong= qh->qhmem.totlong;
  436. *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
  437. memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
  438. }
  439. void qh_meminit(qhT *qh, FILE *ferr) {
  440. memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
  441. if (ferr)
  442. qh->qhmem.ferr= ferr;
  443. else
  444. qh->qhmem.ferr= stderr;
  445. if (sizeof(void *) < sizeof(int)) {
  446. qh_fprintf(qh, qh->qhmem.ferr, 6091, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d. qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
  447. qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
  448. }
  449. }
  450. void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
  451. qh->qhmem.IStracing= tracelevel;
  452. }
  453. void qh_memsetup(qhT *qh) {
  454. }
  455. void qh_memsize(qhT *qh, int size) {
  456. }
  457. void qh_memstatistics(qhT *qh, FILE *fp) {
  458. qh_fprintf(qh, fp, 9409, "\nmemory statistics:\n\
  459. %7d long allocations\n\
  460. %7d long frees\n\
  461. %7d bytes of long memory allocated (max, except for input)\n\
  462. %7d bytes of long memory in use (in %d pieces)\n",
  463. qh->qhmem.cntlong,
  464. qh->qhmem.freelong,
  465. qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong);
  466. }
  467. #endif /* qh_NOmem */
  468. /*-<a href="qh-mem_r.htm#TOC"
  469. >-------------------------------</a><a name="memtotlong">-</a>
  470. qh_memtotal(qh, totlong, curlong, totshort, curshort, maxlong, totbuffer )
  471. Return the total, allocated long and short memory
  472. returns:
  473. Returns the total current bytes of long and short allocations
  474. Returns the current count of long and short allocations
  475. Returns the maximum long memory and total short buffer (minus one link per buffer)
  476. Does not error (for deprecated UsingLibQhull.cpp in libqhullpcpp)
  477. */
  478. void qh_memtotal(qhT *qh, int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
  479. *totlong= qh->qhmem.totlong;
  480. *curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
  481. *totshort= qh->qhmem.totshort;
  482. *curshort= qh->qhmem.cntshort + qh->qhmem.cntquick - qh->qhmem.freeshort;
  483. *maxlong= qh->qhmem.maxlong;
  484. *totbuffer= qh->qhmem.totbuffer;
  485. } /* memtotlong */