/* 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); }
/* 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); }
/* fut_new_chan allocates and initializes a fut_chan_t data structure. * If a required input table is missing, a ramp of the proper grid size * will be created. If a supplied itbl is not required, it will not be * inserted into the channel's private itbl list. All tables which are * actually used are copied and so the caller is responsible for * freeing the passed tables if necessary. * * If VARARGS is used, the list of input tables may be relaced by a * single array of fut_itbl_t pointers. This array must then be followed * by a fut_gtbl_p and a fut_otbl_p. */ fut_chan_p fut_new_chan ( KpInt32_t iomask, fut_itbl_p FAR* itbls, fut_gtbl_p gtbl, fut_otbl_p otbl) { fut_itbl_p itbl[FUT_NCHAN]; fut_chan_p chan; KpInt32_t imask, i, tIndex; /* get input mask */ imask = (KpInt32_t)FUT_IMASK(iomask); /* get args specified by imask */ for ( i=0, tIndex = 0; i<FUT_NCHAN; i++ ) { itbl[i] = ((imask & FUT_BIT(i)) && (itbls != NULL)) ? itbls[tIndex++] : NULL; } /* allocate and clear the fut_chan_t structure */ chan = fut_alloc_chan (); if ( ! IS_CHAN(chan)) { return (NULL); } /* check for valid grid and output tables */ if (( ! IS_GTBL(gtbl)) || ((otbl != NULL) && ( ! IS_OTBL(otbl))) ) { DIAG("fut_new_chan: invalid grid or output table.\n", 0); fut_free_chan (chan); return (NULL); } /* get required input channels from gtbl */ chan->imask = fut_gtbl_imask(gtbl); /* insert the required input tables */ for ( i=0; i<FUT_NICHAN; i++ ) { if ( (chan->imask & FUT_BIT(i)) == 0 ) continue; if ( itbl[i] == FUT_NULL_ITBL ) { chan->itbl[i] = fut_new_itblEx (KCP_REF_TABLES, KCP_FIXED_RANGE, gtbl->size[i], fut_irampEx, NULL); if ( chan->itbl[i] == NULL) { DIAG("fut_new_chan: can't create itbl.\n",0); fut_free_chan (chan); return (NULL); } chan->itblHandle[i] = chan->itbl[i]->handle; } else { if ( ! IS_ITBL (itbl[i])) { DIAG("fut_new_chan: invalid input table.\n", 0); fut_free_chan (chan); return (NULL); } else { if ( itbl[i]->size != gtbl->size[i] ) { DIAG("fut_new_chan: gtbl-itbl size mismatch.\n", 0); fut_free_chan (chan); return (NULL); } else { chan->itbl[i] = fut_share_itbl(itbl[i]); /* share the input table */ chan->itblHandle[i] = chan->itbl[i]->handle; } } } } /* insert grid and output tables */ chan->gtbl = fut_share_gtbl (gtbl); chan->gtblHandle = (IS_GTBL(chan->gtbl)) ? chan->gtbl->handle : FUT_NULL_HANDLE; if (IS_OTBL(otbl)) { chan->otbl = fut_share_otbl (otbl); } else { chan->otbl = fut_alloc_otbl(); } chan->otblHandle = (IS_OTBL(chan->otbl)) ? chan->otbl->handle : FUT_NULL_HANDLE; return (chan); }
/* 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); }
fut_p constructfut ( KpInt32_t iomask, KpInt32_p sizeArray, fut_calcData_p fData, fut_ifunc_p ifunArray, fut_gfunc_p gfunArray, fut_ofunc_p ofunArray, PTDataClass_t iClass, PTDataClass_t oClass) { fut_p futp; KpInt32_t i1, imask, omask; fut_itbl_p itbls[FUT_NICHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; fut_gtbl_p gtbls[FUT_NOCHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; fut_otbl_p otbls[FUT_NOCHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; fut_ifunc_t ifun; fut_gfunc_t gfun; fut_ofunc_t ofun; fData_t fDataL; fut_calcData_p fDataP; if (sizeArray == NULL) return NULL; if (fData == NULL) { fDataP = &fDataL.std; } else { fDataP = fData; } imask = FUT_IMASK(iomask); omask = FUT_OMASK(iomask); #if defined KCP_DIAG_LOG {KpChar_t string[256], str2[256]; KpInt32_t i1; sprintf (string, "constructfut\n iomask %x, sizeArray[]", iomask); for (i1 = 0; i1 < FUT_NICHAN; i1++) { if ((FUT_BIT(i1) & imask) != 0) { sprintf (str2, " %d", sizeArray[i1]); strcat (string, str2); } } sprintf (str2, ", fData %x, ifunArray %x, gfunArray %x, ofunArray %x, iClass %d, oClass %d\n", fData, ifunArray, gfunArray, ofunArray, iClass, oClass); strcat (string, str2); kcpDiagLog (string);} #endif /* Compute shared input tables: */ for (i1 = 0; i1 < FUT_NICHAN; i1++) { if ((imask & FUT_BIT(i1)) != 0) { if ((ifunArray == NULL) || (ifunArray[i1] == NULL)) { ifun = fut_irampEx; fDataP = &fDataL.std; if (iClass == KCP_VARIABLE_RANGE) { fDataL.scale = KCP_16_TO_8_ENCODING; } else { fDataL.scale = 1.0; } } else { ifun = ifunArray[i1]; } fDataP->chan = i1; /* define the channel # */ itbls[i1] = fut_new_itblEx (KCP_REF_TABLES, iClass, sizeArray[i1], ifun, fDataP); itbls[i1]->id = fut_unique_id (); itbls[i1]->dataClass = iClass; } } /* Compute grid tables and output tables: */ for (i1 = 0; i1 < FUT_NOCHAN; i1++) { if ((omask & FUT_BIT(i1)) != 0) { if ((gfunArray == NULL) || (gfunArray[i1] == NULL)) { gfun = fut_grampEx; } else { gfun = gfunArray[i1]; } fDataP->chan = i1; /* define the channel # */ gtbls[i1] = fut_new_gtblEx (KCP_REF_TABLES, iomask, gfun, fDataP, sizeArray); gtbls[i1]->id = fut_unique_id(); if ((ofunArray == NULL) || (ofunArray[i1] == NULL)) { ofun = fut_orampEx; fDataP = &fDataL.std; if (oClass == KCP_VARIABLE_RANGE) { fDataL.scale = KCP_8_TO_16_ENCODING; } else { fDataL.scale = 1.0; } } else { ofun = ofunArray[i1]; } otbls[i1] = fut_new_otblEx (KCP_REF_TABLES, oClass, ofun, fDataP); otbls[i1]->id = fut_unique_id(); otbls[i1]->dataClass = oClass; } } /* Assemble FuT: */ futp = fut_new (iomask, itbls, gtbls, otbls); fut_free_tbls (FUT_NICHAN, (KpGenericPtr_t *)itbls); fut_free_tbls (FUT_NOCHAN, (KpGenericPtr_t *)gtbls); fut_free_tbls (FUT_NOCHAN, (KpGenericPtr_t *)otbls); if (fut_to_mft (futp) != 1) { /* convert to reference tables */ fut_free (futp); futp = NULL; } return (futp); }
/* 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); }