Exemple #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);
}
Exemple #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);
}
Exemple #3
0
/* fut_defchan defines an output channel for a fut.	Returns FALSE(0) if
 * the output channel is already defined (or fut is NULL), TRUE(1)
 * otherwise.  The size of the grid table (if non-zero) must match those
 * of the corresponding input table.  If they do not, the channel remains
 * undefined and FALSE is returned.
 *
 * If a required input table is missing, the table will be shared
 * with the corresponding one from the list of common itbls.  If there
 * is no such table in the common list, a ramp table is created and
 * inserted into the common itbl list.
 *
 * Since fut_defchan is intended to be used for constructing futs with
 * shared input tables,	if an input table is supplied that conflicts with
 * a table in the common list, an error occurs.
 */
KpInt32_t
	fut_defchan (	fut_p			fut,
					KpInt32_t		iomask,
					fut_itbl_p FAR*	itbls,
					fut_gtbl_p		gtbl,
					fut_otbl_p		otbl)
{
fut_itbl_p	itbl[FUT_NICHAN];
fut_chan_p	chan;
KpInt32_t	imask, i, tIndex;

					/* check for valid fut */
	if ( ! IS_FUT(fut)) {
		return (0);
	}
					/* get input mask */
	imask = (KpInt32_t) FUT_IMASK(iomask);

					/* get args specified by imask */
	for ( i=0, tIndex = 0; i < FUT_NICHAN; i++ ) {
		if ((itbls != NULL) && ((imask & FUT_BIT(i)) != 0)) { 	/* if itbl is in arglist, use it */
			itbl[i] = (fut_itbl_p)itbls[tIndex++];
		}
		else {	/* use itbl from shared itbl list */
			itbl[i] = fut->itbl[i];
		}
	}

	chan = fut_new_chan ((KpInt32_t)(FUT_IN (FUT_ALLIN)), (fut_itbl_p FAR*)itbl, gtbl, otbl);
	if ( ! IS_CHAN(chan)) {
		return (0);
	}

	/* If fut_new_chan created a new itbl (ramp), add it to the
	 * common list.	However, if an itbl in the chan differs from
	 * one in the common list, return an error.
	 */
	for ( i=0; i < FUT_NICHAN; i++ ) {
		if ( chan->itbl[i] == NULL ) {
			continue;
		}
		
		if ( ! IS_ITBL(fut->itbl[i])) {
			fut->itbl[i] = fut_share_itbl(chan->itbl[i]);
			fut->itblHandle[i] = chan->itblHandle[i];
		}
		else {
			if ( fut->itbl[i] != chan->itbl[i] ) {
				DIAG("fut_defchan: conflicting itbls.\n", 0);
				fut_free_chan (chan);
				return (0);
			}
		}
	}

					/* insert channel into fut */
	if ( ! fut_add_chan (fut, iomask, chan) ) {
		fut_free_chan (chan);
		return (0);
	}

	return (1);
}
Exemple #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);
}
/* fut_comp_ilut composes a set of 8 or 12-bit, 256 element look-up tables
 * with the input tables of a fut.  These may have been derived from
 * another separable fut.  A new fut is returned which shares grid and
 * output tables with the original but has new input tables.
 *
 * Iomask usage:
 *	imask => luts defined in vararglist to be composed with itbls.
 *		A NULL imask indicates one lut which is composed with
 *		the first defined input table.
 *	omask => unused
 *	pmask => unused
 *	INPLACE may be set to perform the composition in place,
 *		replacing the existing itbls and returning a pointer
 *		to the original fut.
 *	VARARGS may be used to specify an array of luts.
 *	12BITS  if set, supplied luts are 12-bit data (KpInt16_t).
 *		Otherwise, they are 8-bit (KpUInt8_t).
 */
fut_p
	fut_comp_ilut (	fut_p				fut,
					KpInt32_t			iomask,
					KpGenericPtr_t FAR*	srcluts)
{
KpChar_p	luts[FUT_NICHAN];
KpInt32_t	i, i2;
KpInt32_t	imask;
KpInt32_t	is_12bits;
KpInt32_t	in_place;
fut_p		new_fut;
fut_itbl_p	new_itbl;
fut_itbl_p	orig_itbls[FUT_NICHAN];

	if ( ! IS_FUT(fut) )
		return (FUT_NULL);

	/* unpack input mask.  If zero, use first defined channel */
	imask = (KpInt32_t)FUT_IMASK(iomask);
	if (imask == 0 ) {
		imask = (KpInt32_t)FUT_BIT(fut_first_chan((KpInt32_t)fut->iomask.in));
		iomask |= FUT_IN(imask);
	}

					/* get args specified by iomask */
	for ( i=0, i2 = 0; i<FUT_NICHAN; i++ ) {
		if (imask & FUT_BIT(i)) {
			luts[i] = srcluts[i2];	/* save lut address in array */
			i2++;
		}

	}

	/* if INPLACE is not set, create a new fut which shares all of its tables */
	in_place = (KpInt32_t)FUT_IPMASK(iomask);
	if ( in_place ) {
		new_fut = fut;
	}
	else {
		new_fut = fut_copy (fut);
	}

					/* unpack 12bit data flag */
	is_12bits = (KpInt32_t)FUT_12BMASK(iomask);

	/* for each lut passed, compose it with the specified input table(s) */
	/* start by composing the common itbls */
	for ( i=0; i<FUT_NICHAN; i++) {
		/* save original itbls for future comparison */
		orig_itbls[i] = fut->itbl[i];

		/* if no lut or no itbl, there's nothing to do. */
		if ( luts[i] == 0 || fut->itbl[i] == FUT_NULL_ITBL )
			continue;

		/* compose itbl with fut and replace the existing one. */
		new_itbl = fut_comp_itbl_ilut (fut->itbl[i], luts[i], is_12bits);
		if ( new_itbl == FUT_NULL_ITBL ) {
			if ( ! in_place )
				fut_free (new_fut);
			return (FUT_NULL);
		}
		fut_free_itbl (new_fut->itbl[i]);
		new_fut->itbl[i] = new_itbl;
	}

	/* now compose the itbls in each chan, re-sharing if possible */
	for ( i=0; i<FUT_NOCHAN; i++) {
		if ( new_fut->chan[i] == FUT_NULL_CHAN )
			continue;

		if ( ! fut_comp_chan_ilut (new_fut->chan[i], (KpChar_p FAR*)luts,
									orig_itbls, new_fut->itbl, is_12bits) ) {
			if ( ! in_place ) {
				fut_free (new_fut);
			}

			return (FUT_NULL);
		}
	}

	return (new_fut);
}
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);
}
Exemple #7
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;
}