Exemplo n.º 1
0
/* fut_new_gtbl creates a new grid table and optionally intializes it.
 * The input channels defined for the grid are specified in the input
 * channel mask portion of iomask.	Each input defined must have a size
 * specified in a KpInt32_t array.
 * Gfun must be a pointer to a function accepting from zero to three
 * doubles (depending on values of sx, sy, and sz) in the range (0.0,1.0)
 * and returning a fut_gtbldat_t in the range (0,FUT_GRD_MAXVAL).
 * A pointer to the newly allocated table is returned if there were no
 * errors.	(If gfun is NULL, the table is not initialized).
 */
fut_gtbl_p
	fut_new_gtblEx (	PTTableType_t	tableType,
						KpInt32_t		iomask,
						fut_gfunc_t		gfun,
						fut_calcData_p	data,
						KpInt32_p		dimList)
{
fut_gtbl_p	gtbl;
KpInt32_t	imask, i, dim_size, grid_size;

					/* get input mask */
	imask = (KpInt32_t)FUT_IMASK(iomask);

					/* allocate grid table structure */
	gtbl = fut_alloc_gtbl ();
	if ( gtbl == FUT_NULL_GTBL ) {
		DIAG("fut_new_gtblA: can't alloc grid table struct.\n", 0);
		return (FUT_NULL_GTBL);
	}

	/* get sizes from dimList */
	grid_size = 1;
	for ( i=0; i<FUT_NCHAN; i++ ) {
		dim_size = (imask & FUT_BIT(i)) ? dimList[i] : 1;
		if ( dim_size <= 0 ) {
			dim_size = 1;		/* make sure > 0 */
		}
		gtbl->size[i] = (KpInt16_t)dim_size;
		grid_size *= (KpInt32_t)dim_size;
	}

					/* check for valid grid size */
	if ( grid_size <= 0 || grid_size > FUT_GRD_MAX_ENT ) {
		DIAG("fut_new_gtblA: bad grid table size (%d).\n", grid_size);
		fut_free_gtbl(gtbl);
		return (FUT_NULL_GTBL);
	}
	gtbl->tbl_size = (KpInt32_t)grid_size * (KpInt32_t)sizeof(fut_gtbldat_t);

					/* allocate grid table */
	if (tableType == KCP_PT_TABLES) {
		gtbl->refTbl = fut_alloc_gtbldat (gtbl);
	} else {
		gtbl->refTbl = fut_alloc_gmftdat (gtbl);
	}
	if ( gtbl->refTbl == NULL ) {
		DIAG("fut_new_gtblA: can't alloc grid table array.\n", 0);
		fut_free_gtbl(gtbl);
		return (FUT_NULL_GTBL);
	}

					/* compute the grid table entries */
	if ( ! fut_calc_gtblEx (gtbl, gfun, data) ) {
		fut_free_gtbl(gtbl);
		return (FUT_NULL_GTBL);
	}

	return (gtbl);
}
Exemplo n.º 2
0
/* fut_free_gtbl_p
		This function is passed a fut_gtbl_t pointer
		and handle.	If the ref count is zero, the table and
		the fut_gtbl_t is freed.  Otherwise the ref count is 
		decremented and the lock state of the fut_gtbl_t
		is returned to it's state on entry.
*/
static void
	fut_free_gtbl_p (	fut_gtbl_p	gtblP,
						KpHandle_t	gtblHdl)
{
fut_gtbl_p	gtbl = gtblP;

	if (gtblHdl == NULL) {
		return;
	}

	if (gtbl == NULL) {				/* gtbl is unlocked on entry */
		gtbl = lockBuffer(gtblHdl);
	}
	
	if (IS_GTBL(gtbl)) {
		if (gtbl->ref == 0) {
			fut_free_gtbl(gtbl);	/* last reference being freed */
		}
		else {
			if (gtbl->ref > 0) {	/* still other references, leave in original lock state */
				gtbl->ref--;
				if (gtblP == NULL) {
					unlockBuffer(gtblHdl);
				}
			}
		}
	}
}
Exemplo n.º 3
0
/* fut_free_tbl frees any table regardless of type by checking the magic
 * number in the header.  It will also free a fut_t or a fut_chan_t.
 *
 * fut_free_tbls will free a null terminated list of any type of table,
 * useful for disposing of a set of tables which were used for constructing
 * a fut (which the fut has now absorbed and made shared copies of).
 */
void
	fut_free_tbl (KpGenericPtr_t tbl)
{
	/* Make sure that we do not have a NULL pointer */
	if( tbl == NULL ) {
		return;
	}

	switch (*(KpInt32_p)tbl) {
		case FUT_MAGIC:
		fut_free ((fut_p) tbl);
		break;

		case FUT_CMAGIC:
		fut_free_chan ((fut_chan_p) tbl);
		break;

		case FUT_IMAGIC:
		fut_free_itbl ((fut_itbl_p) tbl);
		break;

		case FUT_OMAGIC:
		fut_free_otbl ((fut_otbl_p) tbl);
		break;

		case FUT_GMAGIC:
		fut_free_gtbl ((fut_gtbl_p) tbl);
		break;
	}
}
Exemplo n.º 4
0
/* fut_copy_gtbl makes an exact copy of an existing fut_gtbl_t
 */
fut_gtbl_p
	fut_copy_gtbl (fut_gtbl_p gtbl)
{
fut_gtbl_p		new_gtbl;
KpInt32_t		gsize;
KpHandle_t		h;

				/* check for valid gtbl */
	if ( ! IS_GTBL(gtbl) ) {
		return (FUT_NULL_GTBL);
	}

	new_gtbl = fut_alloc_gtbl ();	/* allocate the new gtbl structure */
	if ( new_gtbl == FUT_NULL_GTBL ) {
		DIAG("fut_copy_gtbl: can't alloc grid table struct.\n", 0);
		return (FUT_NULL_GTBL);
	}

	h = new_gtbl->handle;	/* save handle before copying over old gtbl */

	*new_gtbl = *gtbl;		/* copy entire struct except reference count */

	new_gtbl->handle = h;
	new_gtbl->ref = 0;		/* first reference */

	if (gtbl->tbl != NULL) {	/* copy fixed gtbl data */
		gsize = gtbl->tbl_size / (KpInt32_t)sizeof(fut_gtbldat_t);
		new_gtbl->tbl = fut_alloc_gtbldat (new_gtbl);
		if ( new_gtbl->tbl == NULL ) {
			DIAG("fut_copy_gtbl: can't alloc grid table array.\n", 0);
			goto ErrOut;
		}
		new_gtbl->tblHandle = getHandleFromPtr((KpGenericPtr_t)new_gtbl->tbl);

		/* copy the table entries */
		KpMemCpy (new_gtbl->tbl, gtbl->tbl, gtbl->tbl_size);
	}

	if (gtbl->refTbl != NULL) {	/* copy reference gtbl data */
		new_gtbl->refTbl = fut_alloc_gmftdat (new_gtbl);
		if (new_gtbl->refTbl == NULL ) {
			DIAG("fut_copy_gtbl: can't alloc ref grid table array.\n", 0);
			goto ErrOut;
		}

		/* copy the table entries */
		KpMemCpy (new_gtbl->refTbl, gtbl->refTbl, gtbl->tbl_size);
	}

	return (new_gtbl);
	

ErrOut:
	fut_free_gtbl (new_gtbl);
	return (FUT_NULL_GTBL);
}
Exemplo n.º 5
0
void
	fut_free_chan (fut_chan_p chan)
{
	if ( ! IS_CHAN(chan) )	/* check if defined */
		return;

	fut_free_itbl_list (chan->itbl);	/* free input tables */

	fut_free_otbl (chan->otbl);		/* free output table */

	fut_free_gtbl (chan->gtbl);		/* free grid table */

				/* free fut_chan_t structure itself */
	chan->magic = 0;
	freeBufferPtr ((KpGenericPtr_t)chan);

}
Exemplo n.º 6
0
fut_p
	fut_comp (fut_p fut1, fut_p fut0, KpInt32_t iomask)
{
KpInt32_t		ok = 1, nGridPoints, omask, evalomask, imask, pmask, order, i, j, nEntries, nOutChans;
fut_p			fut2 = NULL, evalFut = NULL;
fut_itbl_p		oitbls[FUT_NICHAN];
mf2_tbldat_p	indat[FUT_NICHAN], outdat[FUT_NOCHAN];
fut_gtbl_p		fut1_gtbls[FUT_NOCHAN];

	if (( ! IS_FUT(fut0)) || ( ! IS_FUT(fut1))) {
		return (NULL);
	}

	/* extract component masks from iomask */
	omask = FUT_OMASK(iomask);		/* which output chans? */
	pmask = FUT_PMASK(iomask);		/* which ones allowed to pass through? */
	order = FUT_ORDMASK(iomask);	/* which interpolation to use? */
	if ( order == FUT_DEFAULT ) {
		order = fut1->iomask.order;
	}

	/* adjust masks for iomask_check below */
	pmask &= fut0->iomask.out;		/* available for "pass through" */
	if ( omask == 0 ) {				/* required outputs (0 means all) */
		omask = fut1->iomask.out;
	}

	/* see if fut0 can provide required inputs to fut1 */
	imask = fut0->iomask.out;		/* available inputs for fut1 */
	iomask = FUT_OUT(omask) | FUT_IN(imask) | FUT_PASS(pmask);
	if ( ! fut_iomask_check (fut1, iomask) ) {
		return (NULL);
	}

	/* make sure the futs are in the reference state */
	if ((fut_to_mft (fut0) != 1) || (fut_to_mft (fut1) != 1)) {
		return (NULL);
	}	

	/* fut1 will be used to process the grid tables of fut0, placing the
	 * results in the grid tables of fut2.  Fut0's grid table data must first
	 * be passed through its output tables before sending it through fut1's
	 * input tables.  This is accomplished more efficiently by composing
	 * fut1's input tables with fut0's output tables and using these directly
	 * on fut0 grid data rather than the normal input tables.
	 *
	 * Create the result fut (fut2) which will be the composition of fut1
	 * and fut0.  Fut2 will inherit the input tables of fut0 and the output
	 * tables of fut1.  Its grid data will be in the same color coordinates
	 * as fut1's.
	 */
	fut2 = fut_new (FUT_IN(FUT_ALLIN), fut0->itbl, NULL, NULL);
	if ( fut2 == NULL ) {
		return (NULL);
	}

	/* for each desired channel i in fut2, create a new grid table.  The
	 * dimensions of each new grid table are derived from fut0 and fut1
	 * like so:  for every input required for channel i of fut1, form the
	 * union of the input sets of all corresponding fut0 outputs.
	 */

	/* null all io tables and table pointers */
	KpMemSet (oitbls, 0, sizeof(oitbls));

	imask = 0;			/* will be the input mask for all inputs needed to fut1 */
	evalomask = 0;		/* omask for evaluation */

	for (i = 0; (i < FUT_NOCHAN) && ok; i++) {
		KpInt32_t	size[FUT_NICHAN];
		fut_gtbl_p	gtbl;
		KpInt32_t	imask1, imask2;

		fut1_gtbls[i] = NULL;	/* assume not needed */

		if ((omask & FUT_BIT(i)) == 0) {	/* is this output channel needed? */
			continue;						/* no */
		}

		/* if a specified output is to be passed through from fut0, do that here */
		if ( ! IS_CHAN(fut1->chan[i]) && IS_CHAN(fut0->chan[i])) {

			ok = fut_defchan (fut2, FUT_OUT(FUT_BIT(i)), NULL,
							fut0->chan[i]->gtbl, fut0->chan[i]->otbl);

			continue;			/* no need to evaluate this ochan */
		}

		if (! IS_CHAN(fut1->chan[i])) {
			ok = 0;						/* something wrong */
			goto GetOut;
		}

		/* At this point we know that (fut1->chan[i] != 0).  We also
		 * have determined (from iomask_check above) that fut0->chan[j] != 0.
		 */
		imask2 = 0;						/* determine inputs from fut0 needed for this channel */
		imask1 = fut1->chan[i]->imask;	/* inputs used by this chan */

		for (j = 0; (j < FUT_NICHAN) && ok; j++) {
			if ((imask1 & FUT_BIT(j)) != 0) {		/* this input chan is needed */
				if ( ! IS_CHAN(fut0->chan[j])) {	/* available? */
					ok = 0;							/* composition fails */
					goto GetOut;
				}

				if (fut1->itbl[j] != fut1->chan[i]->itbl[j]) {	/* shared itbl? */
					goto nextOChan;								/* nope, ignore this ochan */
				}

				imask2 |= fut0->chan[j]->imask;
			}				
		}

		evalomask |= FUT_BIT(i);	/* will be evalutating this channel */
		imask |= imask1;			/* build mask of all needed inputs */
			
		/* determine required dimensions from mask */
		for (j = 0; j < FUT_NICHAN; j++) {
			size[j] = (imask2 & (KpInt32_t)FUT_BIT(j)) ? fut0->itbl[j]->size : 1;
		}

		/* create the new grid table
		 * insert it along with fut1's output table into fut2
		 */
		gtbl = fut_new_gtblEx (FUT_IN(FUT_ALLIN), NULL, NULL, size);
		ok = fut_defchan (fut2, FUT_OUT(FUT_BIT(i)), NULL, gtbl, fut1->chan[i]->otbl);
		fut_free_gtbl (gtbl);
		if (!ok) {
			goto GetOut;
		}

		fut1_gtbls[i] = fut1->chan[i]->gtbl;	/* collect gtbls for evaluation fut */

		/* verify the input data for the evaluation of the output channel in fut1 */
		for (j = 0; j < FUT_NICHAN; j++) {
			if ((imask1 & FUT_BIT(j)) != 0) {									/* this channel needed as input */
				if ((fut0->chan[j]->imask & (~fut2->chan[i]->imask)) != 0) {	/* it's inputs must be used by output */
					ok = 0;				/* composition fails */
					goto GetOut;
				}
			}
		}
nextOChan:;
	}

	/* collect the gtbls which are the input data for the chan evaluation.
	 * also pre-compose fut0's otbls with fut1's itbls.
	 */
	for (i = 0; i < FUT_NICHAN; i++) {
		oitbls[i] = NULL;

		if (ok) {
			fut_chan_p theChan = fut0->chan[i];
			
			if ((imask & FUT_BIT(i)) == 0) {
				continue;				/* this output from fut0 not required */
			}

			indat[i] = theChan->gtbl->refTbl;	/* collect gtbls: the input data for the evaluation */

			ok = (indat[i] != NULL);
			
			/* allocate memory for composed i/o tables
			 * these have the same size as the output tables of the channel supplying the input */
			if (ok) {
				fut_itbl_p	theITbl = fut1->itbl[i];
				fut_otbl_p	theOTbl = theChan->otbl;

				oitbls[i] = fut_alloc_itbl ();		/* get an itbl */

				oitbls[i]->size = theITbl->size;
				oitbls[i]->dataClass = KCP_FIXED_RANGE;

				nEntries = MAX(theITbl->refTblEntries, theOTbl->refTblEntries);

				ok = (fut_alloc_imftdat (oitbls[i], nEntries) != NULL);

				if (ok) {	/* make input table for evaluation */
					ok = fut_comp_iotblMF (theITbl, theOTbl, oitbls[i]);
				}
			}
		}
	}

	/* make an evaluation fut with the composed I/O tables, fut1's gtbls, and no otbls */
	evalFut = fut_new (iomask, oitbls, fut1_gtbls, NULL);
	if (( ! ok) ||
		(evalFut == NULL) ||		/* if evaluation fut ok */
		(fut_to_mft (fut2) != 1)) {	/* make sure the futs are in the reference state */
		ok = 0;
		goto GetOut;
	}	
	else {	/* Finally, we are ready to pass fut0's grid tables through fut1 */
		for (i = 0, nOutChans = 0; (i < FUT_NOCHAN) && ok; i++) {
			if ((evalomask & FUT_BIT(i)) != 0) {
				fut_gtbl_p	gtbl;
				
				gtbl = fut2->chan[i]->gtbl;
				nGridPoints = gtbl->tbl_size / sizeof (fut_gtbldat_t);	/* grid points for eval */

				if (evalFut->iomask.in != evalFut->chan[i]->imask) {	/* must evaluate this channel singly */
					evalomask &= ~FUT_BIT(i);							/* remove channel from multiple eval list */
					ok = evaluateFut (evalFut, FUT_BIT(i), KCM_USHORT, nGridPoints,
									(KpGenericPtr_t FAR*) indat, (KpGenericPtr_t FAR*) &(gtbl->refTbl));
				}
				else {
					outdat[nOutChans] = gtbl->refTbl;
					nOutChans++;
				}

			}
		}

		/* eval result is composed fut's gtbls */
		ok = evaluateFut (evalFut, evalomask, KCM_USHORT, nGridPoints,
						 (KpGenericPtr_t FAR*) indat, (KpGenericPtr_t FAR*) outdat);
	}

GetOut:
	/* must always free up the evaluation fut and io tables, even if an error occurred! */
	fut_free (evalFut);
	fut_free_tbls (FUT_NICHAN, (void *)oitbls);

	/* check for errors */
	if ( !ok ) {
		fut_free (fut2);
		fut2 = NULL;
	}

	return (fut2);
}