Esempio n. 1
0
/* create a new fut which has shared input tables and calculates the identity function */
fut_p
	fut_new_empty (	KpInt32_t		ndim,
					KpInt32_p		dim,
					KpInt32_t		nchan,
					PTDataClass_t	iClass,
					PTDataClass_t	oClass)
{
fut_p		fut;
KpInt32_t	iomask = 0, i1;

	if ((ndim > FUT_NICHAN) || (nchan > FUT_NOCHAN)) {
		return FUT_NULL;
	}
	
	for (i1 = 0; i1 < ndim; i1++) {
		iomask |= FUT_IN(FUT_BIT(i1));
	}

	for (i1 = 0; i1 < nchan; i1++) {
		iomask |= FUT_OUT(FUT_BIT(i1));
	}

	/* Compute shared input tables, grid tables, and output tables:  */
	fut = constructfut (iomask, dim, NULL, NULL, NULL, NULL, iClass, oClass);

	return (fut);
}
Esempio n. 2
0
fut_p
	get_linlab_fut (KpInt32_t		size,
					double			neutralInput,
					PTDataClass_t	iClass,
					PTDataClass_t	oClass)
{
fut_p		futp;
KpInt32_t	iomask, sizeArray[KCP_THIS_FUT_CHANS];
fut_ifunc_t	ifunArray[KCP_THIS_FUT_CHANS] = {NULL, yzfun, yzfun};
fut_ofunc_t	ofunArray[KCP_THIS_FUT_CHANS] = {ofun, ofun, ofun};
fData_t		fData;

	if (iClass) {}	if (oClass) {}

	#if defined KCP_DIAG_LOG
	{KpChar_t	string[256];
	sprintf (string, "get_linlab_fut\n size %d, neutralInput %f\n", size, neutralInput);
	kcpDiagLog (string); }
	#endif

	iomask = FUT_IN(FUT_XYZ) | FUT_OUT(FUT_XYZ);

	/* define neutral input position and grid point */
	fData.neutralInput = neutralInput;
	fData.neutralgrid = (double)(size / 2) / (double)(size - 1);

	/* assume all dimensions are the same */
	sizeArray[0] = size;
	sizeArray[1] = size;
	sizeArray[2] = size;

	futp = constructfut (iomask, sizeArray, &fData.std, ifunArray, NULL, ofunArray,
						iClass, oClass);

	#if defined KCP_DIAG_LOG
	saveFut (futp, "CP24.fut");
	#endif
				
	return (futp);
}
Esempio n. 3
0
/* fut_new allocates and initializes a new fut_t data structure.
 * iomask specifies which (common) input tables and which output channels
 * are being defined.	Additional channels may be added later using
 * fut_defchan.
 *
 * NOTES:
 *	1. All the tables must be packed into a single array.
 *
 *	2. If a needed input table is not supplied (as determined from the
 *	grid table) or if a supplied input table is NULL, then a ramp
 *	input table will be automatically generated and inserted into
 *	the common itbl list.	The grid sizes are inferred from the
 *	supplied grid tables.
 */
fut_p
	fut_new (	KpInt32_t		iomask,
				fut_itbl_p FAR*	itbls,
				fut_gtbl_p FAR*	gtbls,
				fut_otbl_p FAR*	otbls)
{
fut_itbl_p	itbl[FUT_NICHAN];
fut_otbl_p	otbl[FUT_NOCHAN];
fut_gtbl_p	gtbl[FUT_NOCHAN];
fut_p		fut;
KpInt32_t	tIndex, imask, omask, i;

					/* get input and output masks */
	imask = (KpInt32_t)FUT_IMASK(iomask);
	omask = (KpInt32_t)FUT_OMASK(iomask);
	if ( imask > FUT_ALLIN || omask > FUT_ALLOUT ) {
		DIAG("fut_new: too many input or output channels.\n", 0);
		return (NULL);
	}

	/* get args specified by iomask */
	for ( i=0, tIndex = 0; i<FUT_NICHAN; i++ ) {
		itbl[i] = (((imask & FUT_BIT(i)) != 0) && (itbls != NULL))
					? itbls[tIndex++] : FUT_NULL_ITBL;
	}
	for ( i=0, tIndex = 0; i<FUT_NOCHAN; i++ ) {
		gtbl[i] = FUT_NULL_GTBL;
		otbl[i] = FUT_NULL_OTBL;

		if ((omask & FUT_BIT(i)) != 0) {
			if (gtbls != NULL) {
				gtbl[i] = gtbls[tIndex];
			}

			if (otbls != NULL) {
				otbl[i] = otbls[tIndex];
			}

			tIndex++;
		}
	}

				/* allocate and clear the fut_t structure */
	fut = fut_alloc_fut ();
	if ( fut == NULL ) {
		return (NULL);
	}

				/* set the interpolation order */
	fut->iomask.order = (KpInt32_t)FUT_ORDMASK(iomask);

				/* insert the specified input tables */
	for ( i=0; i<FUT_NICHAN; i++ ) {
		if ( itbl[i] == NULL) continue;
		if ( ! IS_ITBL (itbl[i]) ) {
			fut_free (fut);
			return (NULL);
		}
		fut->iomask.in |= FUT_BIT(i);
		fut->itbl[i] = fut_share_itbl(itbl[i]);
		fut->itblHandle[i] = fut->itbl[i]->handle;
	}

				/* define the specified output channels */
	for ( i=0; i<FUT_NOCHAN; i++ ) {
		if ( gtbl[i] == NULL) continue;
		if ( ! fut_defchan(fut,FUT_OUT(FUT_BIT(i)),NULL,gtbl[i],otbl[i]) ) {
			fut_free (fut);
			return (NULL);
		}
	}
	fut->lutConfig = LUT_TYPE_UNKNOWN;
	return (fut);
}
Esempio n. 4
0
fut_p
	fut_resize (	fut_p		fut,
					KpInt32_p	sizeArray)
{
fut_p		reSizedGtblFut = NULL, gtblFut = NULL, reSizedFut = NULL, identityFut = NULL;
KpInt32_t	i1, i2, iomask, iiomask, imask, omask, sameDims;
fut_chan_p	chan;
fut_itbl_p	itbl, itbls[FUT_NICHAN];
fut_gtbl_p	gtbls[FUT_NOCHAN];
fut_otbl_p	otbls[FUT_NOCHAN];

	#if defined KCP_DIAG_LOG
	kcpDiagLog ("fut_resize\n");
	#endif
	
	if ( ! IS_FUT(fut)) {
		return NULL;
	}

	for (i1 = 0; i1 < FUT_NICHAN; i1++) {
		itbls[i1] = FUT_NULL_ITBL;			/* init to null for freeing on error */
	}

	/* collect the gtbls from the source fut */
	/* make sure that all the gtbls use the same itbls */
	omask = 0;
	
	for (i1 = 0, sameDims = 1; i1 < FUT_NOCHAN; i1++) {
		chan = fut->chan[i1];
		if (IS_CHAN(chan)) {
			for (i2 = 0; i2 < FUT_NICHAN; i2++) {
				itbl = fut->itbl[i2];
				if (chan->itbl[i2] != itbl) {	/* must be shared */
					goto GetOut;
				}
				
				if (IS_ITBL(itbl)) {
					if (itbl->size != sizeArray [i2]) {
						sameDims = 0;			/* not the same */
					}
				}
			}

			omask |= FUT_BIT(i1);			/* resize this chan */
			gtbls[i1] = chan->gtbl;			/* collect gtbls */
		}
		else {
			gtbls[i1] = NULL;
		}
	}

	if (sameDims == 1) {
		return fut;		/* already the right size! */
	}

	imask = fut->iomask.in;
	iomask = FUT_OUT(omask) | FUT_IN(imask);
	
	/* make a new fut with these gtbls and identity itbls and otbls */
	gtblFut = fut_new (iomask, NULL, gtbls, NULL);
	if (gtblFut != NULL) {

		/* make an identity fut with itbls that have the specified sizes */
		iiomask = FUT_OUT(imask) | FUT_IN(imask);
		identityFut = constructfut (iiomask, sizeArray, NULL, NULL, NULL, NULL, KCP_FIXED_RANGE, KCP_FIXED_RANGE);
		if (identityFut != NULL) {
		
			/* compose the new size fut with the gtbl fut */
			reSizedGtblFut = fut_comp (gtblFut, identityFut, 0);
			if (reSizedGtblFut != NULL) {

				/* make a new fut with original itbls, ... */
				for (i1 = 0; i1 < FUT_NICHAN; i1++) {
					if ((imask & FUT_BIT(i1)) != 0) {
						itbls[i1] = fut_copy_itbl (fut->itbl[i1]);			/* copy (do not share!) original itbls */
						if (itbls[i1] == NULL) {
							goto GetOut;
						}
						makeMftiTblDat (itbls[i1]);							/* convert to mft to remove grid size dependancy */
						itbls[i1]->size = reSizedGtblFut->itbl[i1]->size;	/* set new grid size */
						fut_free_itbldat (itbls[i1], freeData);				/* free fixed table, it has incorrect grid indices */
					}
				}

				/* ... resized gtbls, and original otbls */
				for (i1 = 0; i1 < FUT_NOCHAN; i1++) {
					if ((omask & FUT_BIT(i1)) != 0) {
						gtbls[i1] = reSizedGtblFut->chan[i1]->gtbl;	/* collect resized gtbls */
						otbls[i1] = fut->chan[i1]->otbl;			/* and original otbls */
					}
					else {
						gtbls[i1] = NULL;
						otbls[i1] = NULL;
					}
				}

				reSizedFut = fut_new (iomask, itbls, gtbls, otbls);
			}
		}
	}

GetOut:
	fut_free (reSizedGtblFut);	/* free the intermediate futs */
	fut_free (gtblFut);
	fut_free (identityFut);
	fut_free_tbls (FUT_NICHAN, (void **)itbls);

	return (reSizedFut);
}
Esempio n. 5
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);
}
Esempio n. 6
0
/* Determine whether or not temporary memory is needed */
static PTErr_t
	setupEvalList (	KpUInt32_t		numPTs,
					PTTable_p*		evalList,
					KpUInt32_p		ioMaskList,
					PTEvalDTPB_p	evalDef,
					KpUInt32_p		tempMemNeeded)
{
PTErr_t		PTErr = KCP_SUCCESS;
KpInt32_t	i1, i2;
KpInt32_t	finalOutputs, nOutputs, maxOutputs;
KpUInt32_t	thisOmask, thisImask;
KpInt32_t	sizeInData, sizeOutData;
fut_chan_p	futChan;

	thisOmask = calcChanMask (evalDef->dataTypeO, evalDef->nOutputs, evalDef->output);	/* calculate final output mask */
	finalOutputs = calcChans (thisOmask);		/* and number of output channels */
	
	/* does the fut have those outputs? */
	if ((FFUTP(evalList[numPTs -1]->data)->iomask.out & thisOmask) != thisOmask) {
		PTErr = KCP_INVAL_EVAL;
		goto ErrOut;
	}

	nOutputs = finalOutputs;	/* # outputs of fut at the end of the list */
	maxOutputs = 0;				/* none yet */
	
	for (i1 = (numPTs -1); i1 >= 0; i1--) {
		if (nOutputs > maxOutputs) {		/* remember max # outputs needed */
			maxOutputs = nOutputs;
		}

		/* get inputs required for this fut as determined by outputs required from this fut */
		thisImask = 0;
		
		for (i2 = 0; i2 < FUT_NOCHAN; i2++) {
			if (thisOmask & FUT_BIT(i2)) {				/* is this output channel needed? */

				futChan = FCHANP(FFUTP(evalList[i1]->data)->chanHandle[i2]);	/* get pointer to chan */

				thisImask |= (KpUInt32_t)FUT_CHAN_IMASK(futChan);	/* include inputs required for this chan */
			}
		}

		ioMaskList [i1] = FUT_OUT(thisOmask) | FUT_IN(thisImask);	/* store the evaluation I/O mask */
		
		/* set up outputs for preceeding fut in the list */
		thisOmask = thisImask;				/* which are inputs to this fut */
		nOutputs = calcChans (thisOmask);	/* get number of output channels */
	}

	thisImask = calcChanMask (evalDef->dataTypeI, evalDef->nInputs, evalDef->input);	/* calculate input mask for the first fut */
	
	/* does the first fut have the required inputs? */
	if ((thisImask & FFUTP(evalList[0]->data)->iomask.in) != FFUTP(evalList[0]->data)->iomask.in) {
		PTErr = KCP_INVAL_EVAL;
		goto ErrOut;
	}

	/* Is temporary memory required? */
	/* If just one PT, then temporary data memory is not needed */
	/* if more than one PT (serial evaluation), then the number and size of the outputs */
	/* determines whether or not temporary memory is needed */
	
	PTErr = getDataBytes (evalDef->dataTypeI, &sizeInData);	/* get input data size */
	if (PTErr != KCP_SUCCESS) {
		goto ErrOut;
	}

	PTErr = getDataBytes (evalDef->dataTypeO, &sizeOutData);	/* get output data size */
	if (PTErr != KCP_SUCCESS) {
		goto ErrOut;
	}

	if (numPTs == 1) {
		(*tempMemNeeded) = 0;		/* not serial evaluation, no temporary data memory needed */
	}
	else {							/* serial evaluation */
									/* does this require temporary memory? */
		if ((maxOutputs > finalOutputs)
			|| (sizeInData < 2)
			|| (sizeOutData < 2)) {
			(*tempMemNeeded) = 1;				/* yes */
		}
		else {
			(*tempMemNeeded) = 0;				/* no */
		}
	}
	
ErrOut:
	return PTErr;
}