/* fut_free_itbl_list_p This function is passed a list of fut_itbl_t pointers and handles. If the ref count is zero, the table and the fut_itbl_t is freed. Otherwise the ref count is decremented and the lock state of the fut_itbl_t is returned to it's state on entry. */ static void fut_free_itbl_list_p ( fut_itbl_p FAR * itbl_list, KpHandle_t FAR * itblHdl_list) { KpInt32_t i; fut_itbl_p itbl; if ((itbl_list == NULL) || (itblHdl_list == NULL)) { return; } for (i = 0; i < FUT_NICHAN; i++) { itbl = itbl_list[i]; if (itbl == NULL) { itbl = lockBuffer (itblHdl_list[i]); } if (IS_ITBL(itbl)) { if (itbl->ref == 0) { fut_free_itbl (itbl); /* last reference being freed */ itbl_list[i] = NULL; itblHdl_list[i] = NULL; } else { if ( itbl->ref > 0 ) { /* still other references */ itbl->ref--; if (itbl_list[i] == NULL) { /* leave in original lock state */ unlockBuffer(itblHdl_list[i]); } } } } } }
/* 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; } }
/* fut_new_itbl creates a new input table for one dimension of a grid table * of size 'size'. Ifun must be a pointer to a function accepting a double * and returning a double, both in the range (0.0,1.0). A pointer to the * newly allocated table is returned. (If ifun is NULL, table is not * initialized). */ fut_itbl_p fut_new_itblEx ( PTTableType_t tableType, PTDataClass_t iClass, KpInt32_t size, fut_ifunc_t ifun, fut_calcData_p data) { fut_itbl_p itbl; KpInt32_t nEntries; if ((size <= 1) || (size > FUT_GRD_MAXDIM)) { DIAG("fut_new_itbl: bad grid size (%d).\n", size); return (FUT_NULL_ITBL); } /* allocate input table structure */ itbl = fut_alloc_itbl (); if ( ! IS_ITBL(itbl)) { DIAG("fut_new_itbl: can't alloc input table struct.\n", 0); return (FUT_NULL_ITBL); } itbl->size = size; itbl->dataClass = iClass; /* allocate the table */ if (itbl->dataClass == KCP_VARIABLE_RANGE) { nEntries = MF2_STD_ITBL_SIZE; } else { nEntries = FUT_INPTBL_ENT; } if (tableType == KCP_PT_TABLES) { itbl->tbl = fut_alloc_itbldat (itbl); if ( itbl->tbl == NULL ) { DIAG("fut_new_itbl: can't alloc input table array.\n", 0); goto ErrOut; } } else { itbl->refTbl = fut_alloc_imftdat (itbl, nEntries); if ( itbl->refTbl == NULL ) { DIAG("fut_new_itbl: can't alloc input table array.\n", 0); goto ErrOut; } } /* compute the input table entries */ if ( ! fut_calc_itblEx (itbl, ifun, data) ) { /* Note: fut_calc_itbl prints message on error */ goto ErrOut; } return (itbl); ErrOut: fut_free_itbl (itbl); return (FUT_NULL_ITBL); }
/* fut_copy_itbl makes an exact copy of an existing fut_itbl_t */ fut_itbl_p fut_copy_itbl (fut_itbl_p itbl) { fut_itbl_p new_itbl; KpHandle_t h; /* check for valid itbl */ if ( ! IS_ITBL(itbl) ) { return (FUT_NULL_ITBL); } /* allocate the new itbl structure */ new_itbl = fut_alloc_itbl (); if ( new_itbl == FUT_NULL_ITBL ) { DIAG("fut_copy_itbl: can't alloc input table struct.\n", 0); return (FUT_NULL_ITBL); } h = new_itbl->handle; /* save handle before copying over old itbl */ *new_itbl = *itbl; /* copy entire struct except reference count */ new_itbl->handle = h; /* copy back handle */ new_itbl->ref = 0; /* first reference */ if (itbl->tbl != NULL) { /* copy fixed itbl data */ new_itbl->tbl = fut_alloc_itbldat (new_itbl); if ( new_itbl->tbl == NULL ) { DIAG("fut_copy_itbl: can't alloc input table array.\n", 0); goto ErrOut; } new_itbl->tblHandle = getHandleFromPtr((KpGenericPtr_t)new_itbl->tbl); /* copy the table entries */ KpMemCpy (new_itbl->tbl, itbl->tbl, (FUT_INPTBL_ENT+1)*sizeof(fut_itbldat_t)); } if (itbl->refTbl != NULL) { /* copy reference itbl data */ new_itbl->refTbl = fut_alloc_imftdat (new_itbl, new_itbl->refTblEntries); if (new_itbl->refTbl == NULL ) { DIAG("fut_copy_itbl: can't alloc input table array.\n", 0); goto ErrOut; } /* copy the table entries */ KpMemCpy (new_itbl->refTbl, itbl->refTbl, new_itbl->refTblEntries * sizeof (mf2_tbldat_t)); } return (new_itbl); ErrOut: fut_free_itbl (new_itbl); return (FUT_NULL_ITBL); }
static void fut_free_itbl_list (fut_itbl_p FAR * itbl_list) { KpInt32_t i; if ( itbl_list == NULL ) { return; } for ( i=0; i<FUT_NICHAN; i++ ) { fut_free_itbl (itbl_list[i]); itbl_list[i] = NULL; } }
/* fut_comp_chan_ilut composes (in place) the input tables of a * fut output channel with the look-up tables specified in the * list, luts. The original and new input tables from the * parent fut must be passed in order to preserve the sharing * of input tables. */ static KpInt32_t fut_comp_chan_ilut (fut_chan_p chan, KpChar_p FAR* luts, fut_itbl_p FAR* orig_itbls, fut_itbl_p FAR* new_itbls, KpInt32_t is_12bits) { KpInt32_t i; fut_itbl_p new_itbl; if ( ! IS_CHAN(chan) ) { return (0); } /* check each itbl to see if must be computed or shared */ for ( i=0; i<FUT_NICHAN; i++ ) { if ((luts[i] == NULL) || (chan->itbl[i] == NULL)) continue; if ((orig_itbls != NULL) && (chan->itbl[i] == orig_itbls[i])) { new_itbl = fut_share_itbl(new_itbls[i]); } else { new_itbl = fut_comp_itbl_ilut (chan->itbl[i], luts[i], is_12bits); } if (new_itbl == FUT_NULL_ITBL) { return (0); } /* replace with the new composed or shared itbl */ fut_free_itbl (chan->itbl[i]); chan->itbl[i] = new_itbl; } return (1); }
/* 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); }