/* Finds discrete maxima of the tensor (based on emc) and refines them, * storing magnitudes in (malloc'ed) *ls and *vs. Returns the number of * distinct maxima, or -1 on error. ls are sorted in descending order. */ int elfMaximaFind_d(double **ls, double **vs, const double *ten, elfMaximaContext *emc) { unsigned int i; int retval; double *vals; airHeap *heap; if (ls==NULL || vs==NULL || ten==NULL || emc==NULL) return -1; if (emc->vertices_d==NULL) { /* we need to allocate these */ emc->vertices_d = (double*) malloc(sizeof(double)*3*(emc->num/2)); for (i=0; i<emc->num/2; i++) { ELL_3V_COPY(emc->vertices_d+3*i, emc->vertices_f+3*i); } } /* evaluate all unique directions */ vals = (double*) malloc(sizeof(double)*(emc->num/2)); for (i=0; i<emc->num/2; i++) { vals[i]=(*emc->type->sym->s_form_d)(ten, emc->vertices_d+3*i); } heap = airHeapNew(sizeof(double)*3, 20); /* identify discrete maxima */ for (i=0; i<emc->num/2; i++) { unsigned int ni=0; int ismax=1, nb; while (ni<emc->nbstride && (nb=emc->neighbors[emc->nbstride*2*i+ni])!=-1) { if (vals[i]<=vals[nb/2]) { ismax=0; break; } ni++; } if (ismax) { double s=vals[i], v[3]; ELL_3V_COPY(v,emc->vertices_d+3*i); if (emc->refine) /* refine further */ tijk_refine_max_3d_d(&s, v, ten, emc->type, emc->parm); /* add to heap */ airHeapInsert(heap, -s, v); } } /* allocate arrays and return what we have found */ retval=airHeapLength(heap); if (retval>0) { *ls = (double*) malloc(sizeof(double)*retval); *vs = (double*) malloc(sizeof(double)*3*retval); for (i=0; i<(unsigned int)retval; i++) { (*ls)[i]=-airHeapFrontPop(heap, (*vs)+3*i); } } heap=airHeapNix(heap); free(vals); return retval; }
/* Same as airHeapNew, but initializes the new heap with the keys from key * and the optional data from data. If data is non-NULL, it needs to * have the same length as key, or this function will fail. The incr * field of the heap is copied from key (rather than data). */ airHeap *airHeapFromArray(const airArray *key, const airArray *data) { airHeap *h; unsigned int i; if (key==NULL || (data!=NULL && data->len!=key->len)) return NULL; /* unusable input */ h = airHeapNew((data==NULL)?0:data->unit, key->incr); if (heapLenIncr (h, key->len)) { /* could not allocate memory */ airHeapNuke(h); return NULL; } memcpy(h->key, key->data, key->len*sizeof(double)); if (h->data_a!=NULL) memcpy(h->data, data->data, data->len*data->unit); for (i=0; i<key->len; i++) { /* initialize indices to identity */ h->idx[i]=i; h->invidx[i]=i; } heapify(h); return h; }