NBNodeHeap *CreateNodeHeap(size_t nehSize,size_t fhiSize) { NBNodeHeap *nodeheap; nodeheap=New(&gcheap,MRound(sizeof(NBNodeHeap))+MRound(fhiSize)); CreateHeap(&nodeheap->nehHeap,"NodeHeap Entries", MHEAP, sizeof(NBNodeEntry)+nehSize, 0.0, 200, 4000); nodeheap->info=(Ptr)(((char*)nodeheap)+MRound(sizeof(NBNodeHeap))); nodeheap->isize=nehSize; nodeheap->count=nodeheap->exps=nodeheap->length=0; nodeheap->head=NULL; nodeheap->id=1; return nodeheap; }
/* EXPORT->CreateDMatrix: Allocate space for double matrix m[1..nrows][1..ncols] */ DMatrix CreateDMatrix(MemHeap *x, int nrows,int ncols) { size_t vsize; int *i,j; DVector *m; char *p; p = (char *) New(x,DMatrixElemSize(nrows,ncols)); i = (int *) p; *i = nrows; vsize = DVectorElemSize(ncols); m = (DVector *) p; p += MRound((nrows+1)*sizeof(DVector)); for (j=1; j<=nrows; j++, p += vsize) { i = (int *) p; *i = ncols; m[j] = (DVector) p; } return m; }
size_t DMatrixElemSize(int nrows,int ncols) { return MRound(DVectorElemSize(ncols) * nrows + (nrows+1)*sizeof(DVector)); }
/* EXPORT->Dispose: Free item p from memory heap x */ void Dispose(MemHeap *x, void *p) { BlockP head,cur,prev; Boolean found=FALSE; ByteP bp; size_t size,chdr; size_t num,index, *ip; Ptr *pp; if (x->totUsed == 0) HError(5105,"Dispose: heap %s is empty",x->name); switch(x->type){ case MHEAP: head = x->heap; cur=head; prev=NULL; size = x->elemSize; while (cur != NULL && !found) { num = cur->numElem; found = cur->data <= p && (((void*)((ByteP)cur->data+(num-1)*size)) >= p); if (!found) { prev=cur; cur=cur->next; } } if (cur == NULL) HError(5175,"Dispose: Item to free in MHEAP %s not found",x->name); index = ((size_t)p-(size_t)cur->data)/size; cur->used[index/8] &= ~(1 <<(index&7)); if (index < cur->firstFree) cur->firstFree = index; cur->numFree++; x->totUsed--; if (cur->numFree == cur->numElem) { if (cur != head) /* free the whole block */ prev->next = cur->next; else head = cur->next; x->heap = head; x->totAlloc -= cur->numElem; free(cur->data); free(cur->used); free(cur); } if (trace&T_MHP) printf("HMem: %s[M] %u bytes at %p de-allocated\n",x->name,size,p); return; case MSTAK: /* search for item to dispose */ cur = x->heap; if (x->protectStk){ if (cur->firstFree > 0 ) /* s-top in current block */ pp = (Ptr *)((size_t)cur->data+cur->firstFree-sizeof(Ptr)); else{ /* s-top in previous block */ if (cur->next == NULL) HError(5175,"Dispose: empty stack"); pp = (Ptr *)((size_t)cur->next->data+cur->next->firstFree-sizeof(Ptr)); } if (*pp != p) HError(-5175,"Dispose: violation of stack discipline in %s [%p != %p]", x->name, *pp, p); } while (cur != NULL && !found){ /* check current block */ num = cur->numElem; found = cur->data <= p && (((void*)((ByteP)cur->data+num)) > p); if (!found) { /* item not in cur block so delete it */ x->heap = cur->next; x->totAlloc -= cur->numElem; x->totUsed -= cur->firstFree; free(cur->data); free(cur); cur = x->heap; if (trace&T_STK) printf("HMem: deleleting block in %s[S]\n",x->name); } } if (!found) HError(5175,"Dispose: Item to free in MSTAK %s not found",x->name); /* finally cut back the stack in the current block */ size = ((ByteP)cur->data + cur->firstFree) - (ByteP)p; if (((ByteP)cur->data + cur->firstFree) < (ByteP)p) HError(5175,"Dispose: item to free in MSTAK %s is above stack top", x->name); cur->firstFree -= size; cur->numFree += size; x->totUsed -= size; if (trace&T_STK) printf("HMem: %s[S] %u bytes at %p de-allocated\n",x->name,size,p); return; case CHEAP: chdr = MRound(sizeof(size_t)); bp = (ByteP)p-chdr; ip = (size_t *)bp; x->totAlloc -= (*ip + chdr); x->totUsed -= *ip; if (trace&T_CHP) printf("HMem: %s[C] %u+%u bytes at %p de-allocated\n", x->name,chdr,*ip,bp); free(bp); return; } }
/* EXPORT->New: create a new element from heap x */ void *New(MemHeap *x,size_t size) { void *q; BlockP newp; size_t num,bytes,*ip,chdr; Boolean noSpace; Ptr *pp; if (x->elemSize <= 0) HError(5174,"New: heap %s not initialised", (x->name==NULL)? "Unnamed":x->name); switch(x->type){ case MHEAP: /* Element is taken from first available slot in block list. If none found a new block is allocated with num elems determined by the curElem, the grow factor growf and the upper limit maxElem. */ if (size != 0 && size != x->elemSize) HError(5173,"New: MHEAP req for %u size elem from heap %s size %u", size,x->name,x->elemSize); noSpace = x->totUsed == x->totAlloc; if (noSpace || (q=GetElem(x->heap,x->elemSize,x->type)) == NULL) { if (!noSpace) BlockReorder(&(x->heap),1); if (noSpace || (q=GetElem(x->heap,x->elemSize,x->type)) == NULL) { num = (size_t) ((double)x->curElem * (x->growf + 1.0) + 0.5); if (num>x->maxElem) num = x->maxElem; newp = AllocBlock(x->elemSize, num, x->type); x->totAlloc += num; x->curElem = num; newp->next = x->heap; x->heap = newp; if ((q=GetElem(x->heap,x->elemSize,x->type)) == NULL) HError(5191,"New: null elem but just made block in heap %s", x->name); } } x->totUsed++; if (trace&T_MHP) printf("HMem: %s[M] %u bytes at %p allocated\n",x->name,size,q); return q; case CHEAP: chdr = MRound(sizeof(size_t)); q = malloc(size+chdr); if (q==NULL) HError(5105,"New: memory exhausted"); x->totUsed += size; x->totAlloc += size+chdr; ip = (size_t *)q; *ip = size; if (trace&T_CHP) printf("HMem: %s[C] %u+%u bytes at %p allocated\n",x->name,chdr,size,q); return (Ptr)((ByteP)q+chdr); case MSTAK: /* set required size - must alloc on double boundaries */ if (x->protectStk) size += sizeof(Ptr); size = MRound(size); /* get elem from current block if possible */ if ((q=GetElem(x->heap,size,x->type)) == NULL) { /* no space - so add a new (maybe bigger) block */ bytes = (size_t)((double)x->curElem * (x->growf + 1.0) + 0.5); if (bytes > x->maxElem) bytes = x->maxElem; x->curElem = bytes; if (bytes < size) bytes = size; bytes = MRound(bytes); newp = AllocBlock(1, bytes, x->type); x->totAlloc += bytes; newp->next = x->heap; x->heap = newp; if ((q=GetElem(x->heap,size,x->type)) == NULL) HError(5191,"New: null elem but just made block in heap %s", x->name); } x->totUsed += size; if (trace&T_STK) printf("HMem: %s[S] %u bytes at %p allocated\n",x->name,size,q); if (x->protectStk) { pp = (Ptr *)((long)q + size - sizeof(Ptr)); /* #### fix this! */ *pp = q; } return q; } return NULL; /* just to keep compiler happy */ }
NBNodeHeap *PrepareLatNBest(int n,AnsMatchType type,Lattice *lat,Boolean noSort) { NBNodeHeap *nodeheap; LatNodeHeapInfo *nhi; NBNodeEntry *neh; LNode *ln; LatNodeEntryInfo *info; double score,like; int i,ansHashSize; /* Make the NBNodeHeap and AnsMatch hash table */ ansHashSize=NB_HASH_SIZE; nodeheap=CreateNodeHeap(sizeof(LatNodeEntryInfo),MRound(sizeof(LatNodeHeapInfo))+ sizeof(NBNodeEntry*)*ansHashSize); nhi=(LatNodeHeapInfo*)nodeheap->info; nhi->lat=lat; nhi->n=n; nhi->type=type; nhi->ansHashSize=ansHashSize; nhi->ansHashTab=(NBNodeEntry**)(((char*)nhi)+MRound(sizeof(LatNodeHeapInfo))); for (i=0;i<nhi->ansHashSize;i++) nhi->ansHashTab[i]=NULL; /* Sort lattice prior to doing NBest */ if (!noSort) SortLNodes(lat,TRUE,FALSE); nhi->like=LatLAhead(lat,0); SortLArcs(lat,-1); SortLArcs(lat,1); /* Mark lattice nodes with likelihood and reachable status */ like=LatLAhead(lat,1); for (i=0,ln=lat->lnodes;i<lat->nn;i++,ln++) { if (lnType(ln)==LNODE_START) MarkStartReachable(ln); if (lnType(ln)==LNODE_END) MarkEndReachable(ln); } /* Check which nodes are viable and for each viable start */ /* node put a dummy start entry into the nodeheap */ for (i=0,ln=lat->lnodes;i<lat->nn;i++,ln++) { if (ln->sublat!=NULL) HError(9999,"SetUpForNBest: Cannot do NBest through sublats"); if ((ln->n&LNODE_FROM_ST) && (ln->n&LNODE_FROM_EN)) ln->n=lnType(ln)|LNODE_VIABLE; if (lnType(ln)==LNODE_VIABLE_ST && ln->score>LSMALL) { /* Put in dummy start entry for viable start node */ neh=NewNodeEntry(+HUGE_VAL,NULL,nodeheap); info=(LatNodeEntryInfo*)neh->info; info->prev=NULL; info->like=ln->score; info->ln=ln; info->la=NULL; info->narc=NULL; info->hv=0; info->hlink=nhi->ansHashTab[info->hv]; nhi->ansHashTab[info->hv]=neh; } ln->sublat=LNodeMatchPtr(ln,type); } /* Calculate lookahead likelihoods (from end of utterance) so */ /* that we can remove the dummy entries and put them back again */ /* with the correct score */ like=LatLAhead(lat,-1); while(nodeheap->head!=NULL && nodeheap->head->score==+HUGE_VAL) { neh=GetNodeEntry(nodeheap); info=neh->info; score=info->like+info->ln->score; NewNodeEntry(score,neh,nodeheap); } return nodeheap; }