void qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) { va_list args; if (!fp) { if(!qh){ qh_fprintf_stderr(6241, "userprintf_r.c: fp and qh not defined for qh_fprintf '%s'", fmt); qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */ } /* could use qh->qhmem.ferr, but probably better to be cautious */ qh_fprintf_stderr(6232, "Qhull internal error (userprintf_r.c): fp is 0. Wrong qh_fprintf called.\n"); qh_errexit(qh, 6232, NULL, NULL); } va_start(args, fmt); if (qh && qh->ANNOTATEoutput) { /* CHANGE TO SOURCE */ /* fprintf(fp, "[QH%.4d]", msgcode); */ REprintf("[QH%.4d]", msgcode); }else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) { /* CHANGE TO SOURCE */ /* fprintf(fp, "QH%.4d ", msgcode); */ REvprintf(fmt, args); } /* CHANGE TO SOURCE */ /* vfprintf(fp, fmt, args); */ if (fp && (fp != qh_FILEstderr)) { vfprintf(fp, fmt, args); } va_end(args); /* Place debugging traps here. Use with option 'Tn' */ } /* qh_fprintf */
void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) { static int needs_cr= 0; /* True if qh_fprintf needs a CR */ size_t fmtlen= strlen(fmt); va_list args; if (!fp) { /* Do not use qh_fprintf_stderr. This is a standalone program */ fprintf(stderr, "QH6232 qh_fprintf: fp not defined for '%s'", fmt); qh_errexit(6232, NULL, NULL); } if(fmtlen>0){ if(fmt[fmtlen-1]=='\n'){ if(needs_cr && fmtlen>1){ fprintf(fp, "\n"); } needs_cr= 0; }else{ needs_cr= 1; } } if(msgcode>=6000 && msgcode<7000){ fprintf(fp, "Error TQ%d ", msgcode); } va_start(args, fmt); vfprintf(fp, fmt, args); va_end(args); }
void qh_meminit(FILE *ferr) { memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */ qhmem.ferr= ferr; if (sizeof(void*) < sizeof(int)) { qh_fprintf(ferr, 6091, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d. qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int)); qh_errexit(qhmem_ERRqhull, NULL, NULL); } }
/*-<a href="qh-mem.htm#TOC" >-------------------------------</a><a name="meminitbuffers">-</a> qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit ) initialize qhmem if tracelevel >= 5, trace memory allocations alignment= desired address alignment for memory allocations numsizes= number of freelists bufsize= size of additional memory buffers for short allocations bufinit= size of initial memory buffer for short allocations */ void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) { qhmem.IStracing= tracelevel; qhmem.NUMsizes= numsizes; qhmem.BUFsize= bufsize; qhmem.BUFinit= bufinit; qhmem.ALIGNmask= alignment-1; if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) { qh_fprintf(qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment); qh_errexit(qhmem_ERRqhull, NULL, NULL); } qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int)); qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *)); if (!qhmem.sizetable || !qhmem.freelists) { qh_fprintf(qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n"); qh_errexit(qhmem_ERRmem, NULL, NULL); } if (qhmem.IStracing >= 1) qh_fprintf(qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment); } /* meminitbuffers */
static PyObject* py_qhalf(PyObject *self, PyObject *args) { const char *arg; const char *data; int curlong, totlong; /* used !qh_NOmem */ int exitcode, numpoints, dim; coordT *points; boolT ismalloc; char *argv[10]; int argc = 1; char *rest; char *token; /* Defensively copy the string first */ char tempstr[30]; char* ptr = tempstr; char *bp; size_t size; FILE* fin; FILE* fout; if (!PyArg_ParseTuple(args, "ss", &arg, &data)) return NULL; strcpy(tempstr, arg); while(token = strtok_r(ptr, " ", &rest)) { argv[argc] = token; ptr = rest; argc += 1; } argv[0] = "qhalf"; /* Because qhull uses stdin and stdout streams for io, we need to create FILE* stream to simulate these io streams.*/ fin = fmemopen(data, strlen(data), "r"); fout = open_memstream(&bp, &size); if ((fin != NULL) && (fout != NULL)) { /* Now do the usual qhull code (modified from qvoronoi.c). */ qh_init_A(fin, fout, stderr, argc, argv); /* sets qh qhull_command */ exitcode= setjmp(qh errexit); /* simple statement for CRAY J916 */ if (!exitcode) { qh_option("Halfspace", NULL, NULL); qh HALFspace= True; /* 'H' */ qh_checkflags(qh qhull_command, qhalf_hidden_options); qh_initflags(qh qhull_command); if (qh SCALEinput) { fprintf(qh ferr, "\ qhull error: options 'Qbk:n' and 'QBk:n' are not used with qhalf.\n\ Use 'Qbk:0Bk:0 to drop dimension k.\n"); qh_errexit(qh_ERRinput, NULL, NULL); }
void *qh_memalloc(int insize) { void *object; if (!(object= qh_malloc((size_t)insize))) { qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n"); qh_errexit(qhmem_ERRmem, NULL, NULL); } qhmem .cntlong++; qhmem .totlong += insize; if (qhmem.maxlong < qhmem.totlong) qhmem.maxlong= qhmem.totlong; if (qhmem.IStracing >= 5) qh_fprintf(qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong); return object; }
/*-<a href="qh-mem.htm#TOC" >-------------------------------</a><a name="memsetup">-</a> qh_memsetup() set up memory after running memsize() */ void qh_memsetup(void) { int k,i; qsort(qhmem.sizetable, (size_t)qhmem.TABLEsize, sizeof(int), qh_intcompare); qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1]; if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) { qh_fprintf(qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n", qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit); qh_errexit(qhmem_ERRmem, NULL, NULL); } if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) { qh_fprintf(qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n"); qh_errexit(qhmem_ERRmem, NULL, NULL); } for (k=qhmem.LASTsize+1; k--; ) qhmem.indextable[k]= k; i= 0; for (k=0; k <= qhmem.LASTsize; k++) { if (qhmem.indextable[k] <= qhmem.sizetable[i]) qhmem.indextable[k]= i; else qhmem.indextable[k]= ++i; } } /* memsetup */
/*-<a href="qh-mem.htm#TOC" >-------------------------------</a><a name="memstatistics">-</a> qh_memstatistics( fp ) print out memory statistics Verifies that qhmem.totfree == sum of freelists */ void qh_memstatistics(FILE *fp) { int i, count, totfree= 0; void *object; for (i=0; i < qhmem.TABLEsize; i++) { count=0; for (object= qhmem .freelists[i]; object; object= *((void **)object)) count++; totfree += qhmem.sizetable[i] * count; } if (totfree != qhmem .totfree) { qh_fprintf(qhmem.ferr, 6211, "qh_memstatistics internal error: totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree); qh_errexit(qhmem_ERRqhull, NULL, NULL); } qh_fprintf(fp, 9278, "\nmemory statistics:\n\ %7d quick allocations\n\ %7d short allocations\n\ %7d long allocations\n\ %7d short frees\n\ %7d long frees\n\ %7d bytes of short memory in use\n\ %7d bytes of short memory in freelists\n\ %7d bytes of dropped short memory\n\ %7d bytes of unused short memory (estimated)\n\ %7d bytes of long memory allocated (max, except for input)\n\ %7d bytes of long memory in use (in %d pieces)\n\ %7d bytes of short memory buffers (minus links)\n\ %7d bytes per short memory buffer (initially %d bytes)\n", qhmem .cntquick, qhmem .cntshort, qhmem .cntlong, qhmem .freeshort, qhmem .freelong, qhmem .totshort, qhmem .totfree, qhmem .totdropped + qhmem .freesize, qhmem .totunused, qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong, qhmem .totbuffer, qhmem .BUFsize, qhmem .BUFinit); if (qhmem.cntlarger) { qh_fprintf(fp, 9279, "%7d calls to qh_setlarger\n%7.2g average copy size\n", qhmem.cntlarger, ((float)qhmem.totlarger)/(float)qhmem.cntlarger); qh_fprintf(fp, 9280, " freelists(bytes->count):"); } for (i=0; i < qhmem.TABLEsize; i++) { count=0; for (object= qhmem .freelists[i]; object; object= *((void **)object)) count++; qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count); } qh_fprintf(fp, 9282, "\n\n"); } /* memstatistics */
/*-<a href="qh-mem.htm#TOC" >-------------------------------</a><a name="memsize">-</a> qh_memsize( size ) define a free list for this size */ void qh_memsize(int size) { int k; if (qhmem .LASTsize) { qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n"); qh_errexit(qhmem_ERRqhull, NULL, NULL); } size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask; for (k=qhmem.TABLEsize; k--; ) { if (qhmem.sizetable[k] == size) return; } if (qhmem.TABLEsize < qhmem.NUMsizes) qhmem.sizetable[qhmem.TABLEsize++]= size; else qh_fprintf(qhmem.ferr, 7060, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes); } /* memsize */
void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) { va_list args; if (!fp) { fprintf(stderr, "QH6232 Qhull internal error (userprintf.c): fp is 0. Wrong qh_fprintf called.\n"); qh_errexit(6232, NULL, NULL); } va_start(args, fmt); #if qh_QHpointer if (qh_qh && qh ANNOTATEoutput) { #else if (qh ANNOTATEoutput) { #endif fprintf(fp, "[QH%.4d]", msgcode); } else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) { fprintf(fp, "QH%.4d ", msgcode); } vfprintf(fp, fmt, args); va_end(args); /* Place debugging traps here. Use with option 'Tn' */ } /* qh_fprintf */
/*-<a href="qh-mem.htm#TOC" >--------------------------------</a><a name="memcheck">-</a> qh_memcheck( ) */ void qh_memcheck(void) { int i, count, totfree= 0; void *object; if (qhmem.ferr == 0 || qhmem.IStracing < 0 || qhmem.IStracing > 10 || (((qhmem.ALIGNmask+1) & qhmem.ALIGNmask) != 0)) { qh_fprintf_stderr(6244, "qh_memcheck error: either qhmem is overwritten or qhmem is not initialized. Call qh_meminit() or qh_new_qhull() before calling qh_mem routines. ferr 0x%x IsTracing %d ALIGNmask 0x%x", qhmem.ferr, qhmem.IStracing, qhmem.ALIGNmask); qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */ } if (qhmem.IStracing != 0) qh_fprintf(qhmem.ferr, 8143, "qh_memcheck: check size of freelists on qhmem\nqh_memcheck: A segmentation fault indicates an overwrite of qhmem\n"); for (i=0; i < qhmem.TABLEsize; i++) { count=0; for (object= qhmem.freelists[i]; object; object= *((void **)object)) count++; totfree += qhmem.sizetable[i] * count; } if (totfree != qhmem.totfree) { qh_fprintf(qhmem.ferr, 6211, "Qhull internal error (qh_memcheck): totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree); qh_errexit(qhmem_ERRqhull, NULL, NULL); } if (qhmem.IStracing != 0) qh_fprintf(qhmem.ferr, 8144, "qh_memcheck: total size of freelists totfree is the same as qhmem.totfree\n", totfree); } /* memcheck */
/*-<a href="qh-mem.htm#TOC" >--------------------------------</a><a name="memalloc">-</a> qh_memalloc( insize ) returns object of insize bytes qhmem is the global memory structure returns: pointer to allocated memory errors if insufficient memory notes: use explicit type conversion to avoid type warnings on some compilers actual object may be larger than insize use qh_memalloc_() for inline code for quick allocations logs allocations if 'T5' design: if size < qhmem.LASTsize if qhmem.freelists[size] non-empty return first object on freelist else round up request to size of qhmem.freelists[size] allocate new allocation buffer if necessary allocate object from allocation buffer else allocate object with qh_malloc() in user.c */ void *qh_memalloc(int insize) { void **freelistp, *newbuffer; int idx, size, n; int outsize, bufsize; void *object; if (insize<0) { qh_fprintf(qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d). Did int overflow due to high-D?\n", insize); /* WARN64 */ qh_errexit(qhmem_ERRmem, NULL, NULL); } if (insize>=0 && insize <= qhmem.LASTsize) { idx= qhmem.indextable[insize]; outsize= qhmem.sizetable[idx]; qhmem.totshort += outsize; freelistp= qhmem.freelists+idx; if ((object= *freelistp)) { qhmem.cntquick++; qhmem.totfree -= outsize; *freelistp= *((void **)*freelistp); /* replace freelist with next object */ #ifdef qh_TRACEshort n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort; if (qhmem.IStracing >= 5) qh_fprintf(qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort); #endif return(object); } else { qhmem.cntshort++; if (outsize > qhmem .freesize) { qhmem .totdropped += qhmem .freesize; if (!qhmem.curbuffer) bufsize= qhmem.BUFinit; else bufsize= qhmem.BUFsize; if (!(newbuffer= qh_malloc((size_t)bufsize))) { qh_fprintf(qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize); qh_errexit(qhmem_ERRmem, NULL, NULL); } *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer list */ qhmem.curbuffer= newbuffer; size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask; qhmem.freemem= (void *)((char *)newbuffer+size); qhmem.freesize= bufsize - size; qhmem.totbuffer += bufsize - size; /* easier to check */ /* Periodically test totbuffer. It matches at beginning and exit of every call */ n = qhmem.totshort + qhmem.totfree + qhmem.totdropped + qhmem.freesize - outsize; if (qhmem.totbuffer != n) { qh_fprintf(qhmem.ferr, 6212, "qh_memalloc internal error: short totbuffer %d != totshort+totfree... %d\n", qhmem.totbuffer, n); qh_errexit(qhmem_ERRmem, NULL, NULL); } } object= qhmem.freemem; qhmem.freemem= (void *)((char *)qhmem.freemem + outsize); qhmem.freesize -= outsize; qhmem.totunused += outsize - insize; #ifdef qh_TRACEshort n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort; if (qhmem.IStracing >= 5) qh_fprintf(qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort); #endif return object; } } else { /* long allocation */ if (!qhmem.indextable) { qh_fprintf(qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n"); qh_errexit(qhmem_ERRqhull, NULL, NULL); } outsize= insize; qhmem .cntlong++; qhmem .totlong += outsize; if (qhmem.maxlong < qhmem.totlong) qhmem.maxlong= qhmem.totlong; if (!(object= qh_malloc((size_t)outsize))) { qh_fprintf(qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize); qh_errexit(qhmem_ERRmem, NULL, NULL); } if (qhmem.IStracing >= 5) qh_fprintf(qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, outsize, qhmem.totlong, qhmem.cntlong-qhmem.freelong); } return(object); } /* memalloc */
/*------------------------------------------------- -qhull- hull_dim convex hull of num_points starting at first_point returns: returns facet_list, numfacets, etc. */ void qh_qhull (void) { setT *maxpoints, *vertices; facetT *facet; int numpart, i, numoutside; realT dist; boolT isoutside; qh hulltime= qh_CPUclock; if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2 && qh lower_threshold[qh hull_dim-1] < -REALmax/2) { for (i= qh_PRINTEND; i--; ) { if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0 && !qh GOODthreshold && !qh SPLITthresholds) break; /* in this case, don't set upper_threshold */ } if (i < 0) { if (qh UPPERdelaunay) qh lower_threshold[qh hull_dim-1]= 0.0; else qh upper_threshold[qh hull_dim-1]= 0.0; if (!qh GOODthreshold) qh SPLITthresholds= True; /* build upper-convex hull even if Qg */ /* qh_initqhull_globals errors if Qg without Pdk/etc. */ } } maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim); /* qh_maxmin sets DISTround and other precision constants */ vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points); qh_initialhull (vertices); /* initial qh facet_list */ qh_partitionall (vertices, qh first_point, qh num_points); qh_resetlists (False /*qh visible_list newvertex_list newfacet_list */); qh facet_next= qh facet_list; qh_furthestnext (/* qh facet_list */); if (qh PREmerge) { qh cos_max= qh premerge_cos; qh centrum_radius= qh premerge_centrum; } if (qh ONLYgood) { if (qh GOODvertex > 0 && qh MERGING) { fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging. Use 'Q0'\n"); qh_errexit (qh_ERRinput, NULL, NULL); } if (!(qh GOODthreshold || qh GOODpoint)) { fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\ good point (QGn or QG-n), or a good vertex with 'Q0' (QVn).\n"); qh_errexit (qh_ERRinput, NULL, NULL); } if (qh GOODvertex > 0 && !qh MERGING /* matches qh_partitionall */ && !qh_isvertex (qh GOODvertexp, vertices)) { facet= qh_findbestnew (qh GOODvertexp, qh facet_list, &dist, &isoutside, &numpart); zadd_(Zdistgood, numpart); if (!isoutside) { fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex\n", qh_pointid(qh GOODvertexp)); qh_errexit (qh_ERRinput, NULL, NULL); } if (!qh_addpoint (qh GOODvertexp, facet, False)) { qh_settempfree(&vertices); qh_settempfree(&maxpoints); return; } } qh_findgood (qh facet_list, 0); }