00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include "mem.h"
00039 
00040 #ifndef qhDEFqhull
00041 typedef struct ridgeT ridgeT;
00042 typedef struct facetT facetT;
00043 void    qh_errexit(int exitcode, facetT *, ridgeT *);
00044 #endif
00045 
00046 
00047 
00048 
00049 
00050 qhmemT qhmem= {0};     
00051 
00052 #ifndef qh_NOmem
00053 
00054 
00055   
00056 static int qh_intcompare(const void *i, const void *j);
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 static int qh_intcompare(const void *i, const void *j) {
00067   return(*((int *)i) - *((int *)j));
00068 } 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 void *qh_memalloc(int insize) {
00100   void **freelistp, *newbuffer;
00101   int index, size;
00102   int outsize, bufsize;
00103   void *object;
00104 
00105   if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
00106     index= qhmem.indextable[insize];
00107     freelistp= qhmem.freelists+index;
00108     if ((object= *freelistp)) {
00109       qhmem.cntquick++;  
00110       *freelistp= *((void **)*freelistp);  
00111       return (object);
00112     }else {
00113       outsize= qhmem.sizetable[index];
00114       qhmem.cntshort++;
00115       if (outsize > qhmem .freesize) {
00116         if (!qhmem.curbuffer)
00117           bufsize= qhmem.BUFinit;
00118         else
00119           bufsize= qhmem.BUFsize;
00120         qhmem.totshort += bufsize;
00121         if (!(newbuffer= malloc(bufsize))) {
00122           fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
00123           qh_errexit(qhmem_ERRmem, NULL, NULL);
00124         } 
00125         *((void **)newbuffer)= qhmem.curbuffer;  
00126 
00127         qhmem.curbuffer= newbuffer;
00128         size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
00129         qhmem.freemem= (void *)((char *)newbuffer+size);
00130         qhmem.freesize= bufsize - size;
00131       }
00132       object= qhmem.freemem;
00133       qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
00134       qhmem.freesize -= outsize;
00135       return object;
00136     }
00137   }else {                     
00138     if (!qhmem.indextable) {
00139       fprintf (qhmem.ferr, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
00140       qh_errexit(qhmem_ERRqhull, NULL, NULL);
00141     }
00142     outsize= insize;
00143     qhmem .cntlong++;
00144     qhmem .curlong++;
00145     qhmem .totlong += outsize;
00146     if (qhmem.maxlong < qhmem.totlong)
00147       qhmem.maxlong= qhmem.totlong;
00148     if (!(object= malloc(outsize))) {
00149       fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
00150       qh_errexit(qhmem_ERRmem, NULL, NULL);
00151     }
00152     if (qhmem.IStracing >= 5)
00153       fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
00154   }
00155   return (object);
00156 } 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 void qh_memfree(void *object, int size) {
00178   void **freelistp;
00179 
00180   if (!object)
00181     return;
00182   if (size <= qhmem.LASTsize) {
00183     qhmem .freeshort++;
00184     freelistp= qhmem.freelists + qhmem.indextable[size];
00185     *((void **)object)= *freelistp;
00186     *freelistp= object;
00187   }else {
00188     qhmem .freelong++;
00189     qhmem .totlong -= size;
00190     free (object);
00191     if (qhmem.IStracing >= 5)
00192       fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
00193   }
00194 } 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 void qh_memfreeshort (int *curlong, int *totlong) {
00207   void *buffer, *nextbuffer;
00208 
00209   *curlong= qhmem .cntlong - qhmem .freelong;
00210   *totlong= qhmem .totlong;
00211   for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
00212     nextbuffer= *((void **) buffer);
00213     free(buffer);
00214   }
00215   qhmem.curbuffer= NULL;
00216   if (qhmem .LASTsize) {
00217     free (qhmem .indextable);
00218     free (qhmem .freelists);
00219     free (qhmem .sizetable);
00220   }
00221   memset((char *)&qhmem, 0, sizeof qhmem);  
00222 } 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 void qh_meminit (FILE *ferr) {
00232   
00233   memset((char *)&qhmem, 0, sizeof qhmem);  
00234   qhmem.ferr= ferr;
00235   if (sizeof(void*) < sizeof(int)) {
00236     fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
00237     exit (1);  
00238   }
00239 } 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
00253 
00254   qhmem.IStracing= tracelevel;
00255   qhmem.NUMsizes= numsizes;
00256   qhmem.BUFsize= bufsize;
00257   qhmem.BUFinit= bufinit;
00258   qhmem.ALIGNmask= alignment-1;
00259   if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
00260     fprintf (qhmem.ferr, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
00261     qh_errexit (qhmem_ERRqhull, NULL, NULL);
00262   }
00263   qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
00264   qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
00265   if (!qhmem.sizetable || !qhmem.freelists) {
00266     fprintf(qhmem.ferr, "qhull error (qh_meminit): insufficient memory\n");
00267     qh_errexit (qhmem_ERRmem, NULL, NULL);
00268   }
00269   if (qhmem.IStracing >= 1)
00270     fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
00271 } 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 void qh_memsetup (void) {
00280   int k,i;
00281 
00282   qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
00283   qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
00284   if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
00285     fprintf (qhmem.ferr, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
00286             qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
00287     qh_errexit(qhmem_ERRmem, NULL, NULL);
00288   }
00289   if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) {
00290     fprintf(qhmem.ferr, "qhull error (qh_memsetup): insufficient memory\n");
00291     qh_errexit(qhmem_ERRmem, NULL, NULL);
00292   }
00293   for(k=qhmem.LASTsize+1; k--; )
00294     qhmem.indextable[k]= k;
00295   i= 0;
00296   for(k= 0; k <= qhmem.LASTsize; k++) {
00297     if (qhmem.indextable[k] <= qhmem.sizetable[i])
00298       qhmem.indextable[k]= i;
00299     else
00300       qhmem.indextable[k]= ++i;
00301   }
00302 } 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 void qh_memsize(int size) {
00311   int k;
00312 
00313   if (qhmem .LASTsize) {
00314     fprintf (qhmem .ferr, "qhull error (qh_memsize): called after qhmem_setup\n");
00315     qh_errexit (qhmem_ERRqhull, NULL, NULL);
00316   }
00317   size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
00318   for(k= qhmem.TABLEsize; k--; ) {
00319     if (qhmem.sizetable[k] == size)
00320       return;
00321   }
00322   if (qhmem.TABLEsize < qhmem.NUMsizes)
00323     qhmem.sizetable[qhmem.TABLEsize++]= size;
00324   else
00325     fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
00326 } 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 void qh_memstatistics (FILE *fp) {
00339   int i, count, totfree= 0;
00340   void *object;
00341   
00342   for (i=0; i < qhmem.TABLEsize; i++) {
00343     count=0;
00344     for (object= qhmem .freelists[i]; object; object= *((void **)object))
00345       count++;
00346     totfree += qhmem.sizetable[i] * count;
00347   }
00348   fprintf (fp, "\nmemory statistics:\n\
00349 %7d quick allocations\n\
00350 %7d short allocations\n\
00351 %7d long allocations\n\
00352 %7d short frees\n\
00353 %7d long frees\n\
00354 %7d bytes of short memory in use\n\
00355 %7d bytes of short memory in freelists\n\
00356 %7d bytes of long memory allocated (except for input)\n\
00357 %7d bytes of long memory in use (in %d pieces)\n\
00358 %7d bytes per memory buffer (initially %d bytes)\n",
00359            qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
00360            qhmem .freeshort, qhmem.freelong, 
00361            qhmem .totshort - qhmem .freesize - totfree,
00362            totfree,
00363            qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
00364            qhmem .BUFsize, qhmem .BUFinit);
00365   if (qhmem.cntlarger) {
00366     fprintf (fp, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
00367            qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
00368     fprintf (fp, "  freelists (bytes->count):");
00369   }
00370   for (i=0; i < qhmem.TABLEsize; i++) {
00371     count=0;
00372     for (object= qhmem .freelists[i]; object; object= *((void **)object))
00373       count++;
00374     fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
00375   }
00376   fprintf (fp, "\n\n");
00377 } 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 #else 
00390 
00391 void *qh_memalloc(int insize) {
00392   void *object;
00393 
00394   if (!(object= malloc(insize))) {
00395     fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
00396     qh_errexit(qhmem_ERRmem, NULL, NULL);
00397   }
00398   if (qhmem.IStracing >= 5)
00399     fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", insize, object);
00400   return object;
00401 }
00402 
00403 void qh_memfree(void *object, int size) {
00404 
00405   if (!object)
00406     return;
00407   free (object);
00408   if (qhmem.IStracing >= 5)
00409     fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
00410 }
00411 
00412 void qh_memfreeshort (int *curlong, int *totlong) {
00413 
00414   memset((char *)&qhmem, 0, sizeof qhmem);  
00415   *curlong= 0;
00416   *totlong= 0;
00417 }
00418 
00419 void qh_meminit (FILE *ferr) {
00420 
00421   memset((char *)&qhmem, 0, sizeof qhmem);  
00422   qhmem.ferr= ferr;
00423   if (sizeof(void*) < sizeof(int)) {
00424     fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
00425     qh_errexit (qhmem_ERRqhull, NULL, NULL);
00426   }
00427 }
00428 
00429 void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
00430 
00431   qhmem.IStracing= tracelevel;
00432 
00433 }
00434 
00435 void qh_memsetup (void) {
00436 
00437 }
00438 
00439 void qh_memsize(int size) {
00440 
00441 }
00442 
00443 void qh_memstatistics (FILE *fp) {
00444 
00445 }
00446 
00447 #endif