/* ******** biffMsgMove ** ** "src" is not const because we clear it after moving things out */ void biffMsgMove(biffMsg *dest, biffMsg *src, const char *err) { static const char me[]="biffMsgMove"; unsigned int ii; char *buff; if (biffMsgNoop == dest || biffMsgNoop == src) { return; } if (!( dest && src )) { fprintf(stderr, "%s: PANIC got NULL msg (%p %p)\n", me, AIR_VOIDP(dest), AIR_VOIDP(src)); /* exit(1); */ } /* if src and dest are same, this degenerates to biffMsgAdd */ if (dest == src && airStrlen(err)) { biffMsgAdd(dest, err); return; } buff = AIR_CALLOC(biffMsgLineLenMax(src)+1, char); if (!buff) { fprintf(stderr, "%s: PANIC: can't allocate buffer\n", me); /* exit(1); */ } for (ii=0; ii<src->errNum; ii++) { sprintf(buff, "[%s] %s", src->key, src->err[ii]); biffMsgAdd(dest, buff); } free(buff); biffMsgClear(src); if (airStrlen(err)) { biffMsgAdd(dest, err); } return; }
void airMopDebug(airArray *arr) { airMop *mops; unsigned int ii; mvunion mvu; if (!arr) return; mops = (airMop *)arr->data; printf("airMopDebug: _________________________ mop stack for 0x%p:\n", AIR_VOIDP(arr)); if (arr->len) { ii = arr->len; do { ii--; printf("%4u: ", ii); if (NULL == mops[ii].mop && NULL == mops[ii].ptr && airMopNever == mops[ii].when) { printf("no-op\n"); continue; } /* else */ printf("%s: ", _airMopWhenStr[mops[ii].when]); if (airFree == mops[ii].mop) { printf("airFree(0x%p)\n", AIR_VOIDP(mops[ii].ptr)); continue; } if ((airMopper)airSetNull == mops[ii].mop) { printf("airSetNull(0x%p)\n", AIR_VOIDP(mops[ii].ptr)); continue; } if (_airMopPrint == mops[ii].mop) { printf("_airMopPrint(\"%s\" == 0x%p)\n", AIR_CAST(char*, mops[ii].ptr), AIR_VOIDP(mops[ii].ptr)); continue; } if ((airMopper)airFclose == mops[ii].mop) { printf("airFclose(0x%p)\n", AIR_VOIDP(mops[ii].ptr)); continue; } /* else */ mvu.m = mops[ii].mop; printf("0x%p(0x%p)\n", AIR_VOIDP(mvu.v), AIR_VOIDP(mops[ii].ptr)); } while (ii);
/* ** adds a given message to the given entry. The message is processed to ** convert all whitespace into ' ', and to eliminate whitespace at the ** end of the message. */ void biffMsgAdd(biffMsg *msg, const char *err) { static const char me[]="biffMsgAdd"; unsigned int idx; if (biffMsgNoop == msg) { return; } if (!( msg && err )) { fprintf(stderr, "%s: PANIC got NULL msg (%p) or err (%p)\n", me, AIR_VOIDP(msg), AIR_CVOIDP(err)); /* exit(1); */ } idx = airArrayLenIncr(msg->errArr, 1); if (!msg->err) { fprintf(stderr, "%s: PANIC: couldn't add message to %s\n", me, msg->key); /* exit(1); */ } if (!( msg->err[idx] = airOneLinify(airStrdup(err)) )) { fprintf(stderr, "%s: PANIC: couldn't alloc message to %s\n", me, msg->key); /* exit(1); */ } return; }
/* ** parties until the gradients settle down */ int tenGradientBalance(Nrrd *nout, const Nrrd *nin, tenGradientParm *tgparm) { static const char me[]="tenGradientBalance"; double len, lastLen, improv; airRandMTState *rstate; Nrrd *ncopy; unsigned int iter, maxIter; int done; airArray *mop; if (!nout || tenGradientCheck(nin, nrrdTypeUnknown, 2) || !tgparm) { biffAddf(TEN, "%s: got NULL pointer (%p,%p) or invalid nin", me, AIR_VOIDP(nout), AIR_VOIDP(tgparm)); return 1; } if (nrrdConvert(nout, nin, nrrdTypeDouble)) { biffMovef(TEN, NRRD, "%s: can't initialize output with input", me); return 1; } mop = airMopNew(); ncopy = nrrdNew(); airMopAdd(mop, ncopy, (airMopper)nrrdNuke, airMopAlways); rstate = airRandMTStateNew(tgparm->seed); airMopAdd(mop, rstate, (airMopper)airRandMTStateNix, airMopAlways); /* HEY: factor of 100 is an approximate hack */ maxIter = 100*tgparm->maxIteration; lastLen = 1.0; done = AIR_FALSE; do { iter = 0; do { iter++; len = party(nout, rstate); } while (len > lastLen && iter < maxIter); if (iter >= maxIter) { if (tgparm->verbose) { fprintf(stderr, "%s: stopping at max iter %u\n", me, maxIter); } if (nrrdCopy(nout, ncopy)) { biffMovef(TEN, NRRD, "%s: trouble copying", me); airMopError(mop); return 1; } done = AIR_TRUE; } else { if (nrrdCopy(ncopy, nout)) { biffMovef(TEN, NRRD, "%s: trouble copying", me); airMopError(mop); return 1; } improv = lastLen - len; lastLen = len; if (tgparm->verbose) { fprintf(stderr, "%s: (iter %u) improvement: %g (mean length = %g)\n", me, iter, improv, len); } done = (improv <= tgparm->minMeanImprovement || len < tgparm->minMean); } } while (!done); airMopOkay(mop); return 0; }
int pullInfoSpecAdd(pullContext *pctx, pullInfoSpec *ispec) { static const char me[]="pullInfoSpecAdd"; unsigned int ii, vi, haveLen, needLen; const gageKind *kind; if (!( pctx && ispec )) { biffAddf(PULL, "%s: got NULL pointer", me); return 1; } if (airEnumValCheck(pullInfo, ispec->info)) { biffAddf(PULL, "%s: %d not a valid %s value", me, ispec->info, pullInfo->name); return 1; } if (airEnumValCheck(pullSource, ispec->source)) { biffAddf(PULL, "%s: %d not a valid %s value", me, ispec->source, pullSource->name); return 1; } if (pctx->ispec[ispec->info]) { biffAddf(PULL, "%s: already set info %s (%d)", me, airEnumStr(pullInfo, ispec->info), ispec->info); return 1; } for (ii=0; ii<=PULL_INFO_MAX; ii++) { if (pctx->ispec[ii] == ispec) { biffAddf(PULL, "%s(%s): already got ispec %p as ispec[%u]", me, airEnumStr(pullInfo, ispec->info), AIR_VOIDP(ispec), ii); return 1; } } if (pctx->verbose) { printf("%s: ispec %s from vol %s\n", me, airEnumStr(pullInfo, ispec->info), ispec->volName); } needLen = pullInfoLen(ispec->info); if (pullSourceGage == ispec->source) { vi = _pullVolumeIndex(pctx, ispec->volName); if (UINT_MAX == vi) { biffAddf(PULL, "%s(%s): no volume has name \"%s\"", me, airEnumStr(pullInfo, ispec->info), ispec->volName); return 1; } kind = pctx->vol[vi]->kind; if (airEnumValCheck(kind->enm, ispec->item)) { biffAddf(PULL, "%s(%s): %d not a valid \"%s\" item", me, airEnumStr(pullInfo, ispec->info), ispec->item, kind->name); return 1; } haveLen = kind->table[ispec->item].answerLength; if (needLen != haveLen) { biffAddf(PULL, "%s(%s): need len %u, but \"%s\" item \"%s\" has len %u", me, airEnumStr(pullInfo, ispec->info), needLen, kind->name, airEnumStr(kind->enm, ispec->item), haveLen); return 1; } /* very tricky: seedOnly is initialized to true for everything */ if (pullInfoSeedThresh != ispec->info && pullInfoSeedPreThresh != ispec->info) { /* if the info is neither seedthresh nor seedprethresh, then the volume will have to be probed after the first iter, so turn *off* seedOnly */ pctx->vol[vi]->seedOnly = AIR_FALSE; } /* less tricky: turn on forSeedPreThresh as needed; its initialized to false */ if (pullInfoSeedPreThresh == ispec->info) { pctx->vol[vi]->forSeedPreThresh = AIR_TRUE; if (pctx->verbose) { printf("%s: volume %u %s used for %s\n", me, vi, pctx->vol[vi]->name, airEnumStr(pullInfo, pullInfoSeedPreThresh)); } } /* now set item in gage query */ if (gageQueryItemOn(pctx->vol[vi]->gctx, pctx->vol[vi]->gpvl, ispec->item)) { biffMovef(PULL, GAGE, "%s: trouble adding item %u to vol %u", me, ispec->item, vi); return 1; } ispec->volIdx = vi; } else if (pullSourceProp == ispec->source) { haveLen = pullPropLen(ispec->prop); if (needLen != haveLen) { biffAddf(PULL, "%s: need len %u, but \"%s\" \"%s\" has len %u", me, needLen, pullProp->name, airEnumStr(pullProp, ispec->prop), haveLen); return 1; } } else { biffAddf(PULL, "%s: sorry, source %s unsupported", me, airEnumStr(pullSource, ispec->source)); return 1; } if (haveLen > 9) { biffAddf(PULL, "%s: sorry, answer length (%u) > 9 unsupported", me, haveLen); return 1; } pctx->ispec[ispec->info] = ispec; return 0; }
/* ** nrrdArrayCompare ** ** something like strcmp() for arrays of numeric values, except ** that the arrays have to be equal length, and it has to do ** error checking. ** ** See comment about logic of return value above nrrdCompare() ** ** This is a very rare kind of nrrd function that operates on ** a bare array and not a Nrrd itself */ int nrrdArrayCompare(int type, const void *_valA, const void *_valB, size_t valNum, double epsilon, int *differ, char explain[AIR_STRLEN_LARGE]) { static const char me[]="nrrdArrayCompare"; const unsigned char *valA, *valB; int (*compare)(const void *, const void *); size_t ii, sze; char stmp[AIR_STRLEN_SMALL]; if (!(_valA && _valB && differ)) { biffAddf(NRRD, "%s: got NULL pointer (%p, %p, or %p)", me, _valA, _valB, AIR_VOIDP(differ)); return 1; } if (!valNum) { biffAddf(NRRD, "%s: can't work with 0-length arrays", me); return 1; } if (!AIR_EXISTS(epsilon)) { biffAddf(NRRD, "%s: non-existent epsilon %g", me, epsilon); return 1; } if (airEnumValCheck(nrrdType, type)) { biffAddf(NRRD, "%s: invalid nrrd type %d", me, type); return 1; } if (nrrdTypeBlock == type) { biffAddf(NRRD, "%s: can't use type %s", me, airEnumStr(nrrdType, type)); return 1; } if (explain) { strcpy(explain, ""); } if (type == nrrdTypeLLong || type == nrrdTypeULLong) { fprintf(stderr, "%s: WARNING: possible erroneous comparison of " "%s values with %s-based comparison\n", me, airEnumStr(nrrdType, type), airEnumStr(nrrdType, nrrdTypeDouble)); } sze = nrrdTypeSize[type]; compare = nrrdValCompare[type]; valA = AIR_CAST(const unsigned char *, _valA); valB = AIR_CAST(const unsigned char *, _valB); for (ii=0; ii<valNum; ii++) { *differ = compare(valA + ii*sze, valB + ii*sze); if (*differ) { double aa, bb; /* same loss of precision as warned about above */ aa = nrrdDLookup[type](valA, ii); bb = nrrdDLookup[type](valB, ii); if (0 == epsilon || fabs(aa - bb) > epsilon) { if (explain) { airSprintSize_t(stmp, ii); if (0 == epsilon) { sprintf(explain, "valA[%s]=%.17g %s valB[%s]=%.17g " "by %g", stmp, aa, *differ < 0 ? "<" : ">", stmp, bb, fabs(aa - bb)); } else { sprintf(explain, "valA[%s]=%.17g %s valB[%s]=%.17g " "by %g, more than eps %g", stmp, aa, *differ < 0 ? "<" : ">", stmp, bb, fabs(aa - bb), epsilon); } } break; } else { /* we did detect a difference, but it was not in excess of epsilon, so we reset *differ to 0 */ *differ = 0; } } } return 0; }