Ejemplo n.º 1
0
static Error
_newQMesh(int nStrips, int nStrippedPts, QMesh *mesh, dxObject *o)
{
    Private priv = NULL;
    QMesh tmp = NULL;

    *mesh = NULL;
    *o = NULL;

    tmp = (QMesh)DXAllocateZero(sizeof(QMeshS));
    if (! tmp)
        return ERROR;

    tmp->meshArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2);
    if (! tmp->meshArray)
        goto error;

    DXReference((dxObject)tmp->meshArray);

    if ( !DXAllocateArray (tmp->meshArray, nStrips))
        goto error;

    tmp->connectionArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
    if (! tmp->connectionArray)
        goto error;

    DXReference((dxObject)tmp->connectionArray);

    if ( !DXAllocateArray (tmp->connectionArray, nStrippedPts))
        goto error;

    tmp->meshes       = (int *)DXGetArrayData(tmp->meshArray);
    tmp->connections  = (int *)DXGetArrayData(tmp->connectionArray);
    tmp->nmeshes      = nStrips;
    tmp->nconnections = nStrippedPts;

    priv = (Private)DXNewPrivate((Pointer)tmp, _deleteQMesh);
    if (! priv)
       goto error;

    *mesh = tmp;
    *o = (dxObject)priv;

    return OK;

error:
    if (tmp)
    {
        if (tmp->connectionArray)
            DXDelete((dxObject)tmp->connectionArray);
        if (tmp->meshArray)
            DXDelete((dxObject)tmp->meshArray);

        DXFree((Pointer)tmp);
    }

    return ERROR;
}
Ejemplo n.º 2
0
/*
 * in:   0 = input
 *      (1) = component name
 *
 * out: 0 = avg
 *      1 = std
 *      2 = var
 *      3 = min
 *      4 = max
 */
int
m_Statistics(Object *in, Object *out)
{
    float min, max, avg, stddev, var;
    double dvar;


    if (!in[0]) {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	return ERROR;
    }

    if (!DXStatistics(in[0], "data", &min, &max, &avg, &stddev))
	return ERROR;


    out[0] = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
    if (!out[0] || !DXAddArrayData((Array)out[0], 0, 1, (Pointer)&avg))
	goto error;
			
    out[1] = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
    if (!out[1]  || !DXAddArrayData((Array)out[1], 0, 1, (Pointer)&stddev))
	goto error;

    dvar = (double)stddev * stddev;
    if (dvar > DXD_MAX_FLOAT) {
	out[2] = (Object)DXNewArray(TYPE_DOUBLE, CATEGORY_REAL, 0);
	if (!out[2] || !DXAddArrayData((Array)out[2], 0, 1, (Pointer)&dvar))
	    goto error;
    } else {
	var = (float)dvar;
	out[2] = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
	if (!out[2] || !DXAddArrayData((Array)out[2], 0, 1, (Pointer)&var))
	    goto error;
    }
	
    out[3] = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
    if (!out[3] || !DXAddArrayData((Array)out[3], 0, 1, (Pointer)&min))
	goto error;
			
    out[4] = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
    if (!out[4] || !DXAddArrayData((Array)out[4], 0, 1, (Pointer)&max))
	goto error;


    return OK;

error:
    DXDelete(out[0]);  out[0] = NULL;
    DXDelete(out[1]);  out[1] = NULL;
    DXDelete(out[2]);  out[2] = NULL;
    DXDelete(out[3]);  out[3] = NULL;
    DXDelete(out[4]);  out[4] = NULL;
    return ERROR;

}
Ejemplo n.º 3
0
static Error
_deleteQMesh(void *p)
{
    QMesh t = (QMesh)p;
    if (t->connectionArray)
        DXDelete((dxObject)t->connectionArray);
    if (t->meshArray)
        DXDelete((dxObject)t->meshArray);
   
    DXFree(p);

    return OK;
}
Ejemplo n.º 4
0
Error
m_CategoryStatistics(Object *in, Object *out)
{
  int i;

  out[0] = NULL;

  if (in[0] == NULL)
  {
    DXSetError(ERROR_MISSING_DATA, "\"input\" must be specified");
    return ERROR;
  }

  if (!traverse(in, out))
    goto error;

  return OK;

error:
  for (i = 0; i < 1; i++)
  {
    if (in[i] != out[i])
      DXDelete(out[i]);
    out[i] = NULL;
  }
  return ERROR;
}
Ejemplo n.º 5
0
int
m_Normals (Object *in, Object *out)
{
    char		*method;

    out[0] = NULL;

    if (in[0] == NULL)
    {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	goto error;
    }

    if (in[1])
    {
	if (! DXExtractString(in[1], &method))
	{
	    DXSetError(ERROR_BAD_PARAMETER, "#10200", "method");
	    goto error;
	}
    }
    else
	method = "positions";

    out[0] = _dxfNormals(in[0], method);

    if (out[0] == NULL || DXGetError() != ERROR_NONE)
	goto error;
    
    return OK;

error:
    DXDelete(out[0]);
    return ERROR;
}
Ejemplo n.º 6
0
static Field
RefineField(Field field, char *args, int l)
{
    int	  limit = ((Args *)args)->limit;
    Field newField;
    Array array;

    if (DXEmptyField(field))
	return DXEndField(DXNewField());
    
    field = (Field)DXCopy((Object)field, COPY_STRUCTURE);
    if (! field)
	return NULL;

    array = (Array)DXGetComponentValue(field, "connections");

    if (DXQueryGridConnections(array, NULL, NULL))
	newField = _dxfRefineReg(field, limit);
    else
	newField = _dxfRefineIrreg(field, limit);

    if (newField == NULL)
	DXDelete((Object)field);
    
    return newField;
}
Ejemplo n.º 7
0
Error
m_MakeXEfficient(Object *in, Object *out)
{
    int i;

    /*
     * Initialize all outputs to NULL
     */
    out[0] = NULL;

    /*
     * Error checks: required inputs are verified.
     */

    /* Parameter "input" is required. */
    if (in[0] == NULL)
    {
        DXSetError(ERROR_MISSING_DATA, "\"input\" must be specified");
        return ERROR;
    }


    /*
     * Since output "output" is structure Field/Group, it initially
     * is a copy of input "input".
     */
    out[0] = DXCopy(in[0], COPY_STRUCTURE);
    if (! out[0])
        goto error;

    /*
     * If in[0] was an array, then no copy is actually made - Copy
     * returns a pointer to the input object.  Since this can't be written to
     * we postpone explicitly copying it until the leaf level, when we'll need
     * to be creating writable arrays anyway.
     */
    if (out[0] == in[0])
        out[0] = NULL;

    /*
     * Call the hierarchical object traversal routine
     */
    if (!traverse(in, out))
        goto error;

    return OK;

error:
    /*
     * On error, any successfully-created outputs are deleted.
     */
    for (i = 0; i < 1; i++)
    {
        if (in[i] != out[i])
            DXDelete(out[i]);
        out[i] = NULL;
    }
    return ERROR;
}
Ejemplo n.º 8
0
/* get rid of last input object set */
Error DXFreeInputs()
{
    if (last_inputs) {
	DXDelete (last_inputs);
	last_inputs = NULL;
    }
    return OK;
}
Ejemplo n.º 9
0
Error m_MachNumber (Object * in,Object * out) {
   Object * get;
   int fields,i,ngases;

   /* Verify input */
   if (in[0]==NULL) {
      DXSetError(ERROR_MISSING_DATA,"Input field 0 must be specified");
      goto error;
   }
   if (!DXExtractInteger(in[0],&ngases)) {
      DXSetError(ERROR_DATA_INVALID,"Could not extract INTEGER from field 0");
      goto error;
   }
   fields=INPUT_FIELDS+ngases;
   if (ngases < NGASES_MIN || ngases > NGASES_MAX) {
      DXSetError(ERROR_BAD_PARAMETER,
                 "The value of input field 0 must be %d <= X <= %d",
                 NGASES_MIN,NGASES_MAX);
      goto error;
   }
   for (i=1; i<fields; i++) {
      if (in[i]==NULL) {
         DXSetError(ERROR_MISSING_DATA,"Input field %d must be specified",i);
         goto error;
      }
   }

   /* Since this module is meant to operate on an existing Field / MultiGrid
    * object, initialize the output fields as a copy of the second input
    * field.  */
   for (i=0; i<OUTPUT_FIELDS; i++) {
      if (!(out[i]=DXCopy(in[1],COPY_STRUCTURE)))
         goto error;
      /* If in[1] is an array, DXCopy() will return a pointer to the input
       * object. Since this cannot be written to, an exception will be
       * raised.  */
      if (in[1]==out[i]) {
         DXSetError(ERROR_DATA_INVALID,
                    "Input fields 1-%d should be Field / MultiGrid objects",
                    fields);
         goto error;
      }
   }

   /* Skip the first input field as it is not a Field / MultiGrid object.  */
   get=in+1;
   if (!traverse (w_MachNumber,get,fields-1,out,OUTPUT_FIELDS))
      goto error;

   return OK;
   
error:
   for (i=0; i<OUTPUT_FIELDS; i++) {
      DXDelete(out[i]);
      out[i]=NULL;
   }
   return ERROR;
}
Ejemplo n.º 10
0
static void
Slide2DEndMode(void *data)
{
    Slide2DData sdata = (Slide2DData)data;

    /*
     * Clean up
     */
    if (sdata)
    {
	if (sdata->args)
	    DXDelete(sdata->args);
	
	if (sdata->obj)
	    DXDelete(sdata->obj);
    }

    DXFree(data);
}
Ejemplo n.º 11
0
Error
_dxf_polylinesToPlines (xfieldT *xf)
{
  int		i;
  int		start, end, knt;
  int		*mesh;

  ENTRY(("_dxf_linesToPlines(0x%x)", xf));
  
  /* allocate permanent xfield pline data of appropriate size */
  /* Allocations are a guess based on 100 lines/polyline */

  if (!(xf->meshes = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2)) ||
      !(DXAllocateArray (xf->meshes, xf->npolylines)))
    {
      PRINT(("could not allocate xfield mesh data"));
      DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;
    }

  mesh = (int *)DXGetArrayData(xf->meshes);

  for (i = 0; i < xf->npolylines; i++)
  {
      start = xf->polylines[i];
      end   = (i+1 == xf->npolylines) ? xf->nedges : xf->polylines[i+1];
      knt   = end - start;

      if(xf->invCntns && !DXIsElementValid(xf->invCntns,i)) continue;

      *mesh++ = start;
      *mesh++ = knt;
  }

  xf->connections_array = (Array)DXReference((dxObject)xf->edges);
  xf->nconnections = xf->nedges;

  xf->nmeshes = xf->npolylines;

  /* record connection info */
  xf->posPerConn = 1 ;
  xf->connectionType = ct_pline;

  EXIT(("OK"));
  return OK ;

 error:

  if(xf->meshes) DXDelete((dxObject)xf->meshes);

  EXIT(("ERROR"));
  return 0 ;
}
Ejemplo n.º 12
0
dxObject
_dxfSaveHardwareWindow(char *where)
{
    Private           cacheObject = NULL;
    tdmChildGlobalP   globals = NULL;
    char*             cacheId = NULL;
    tdmParsedFormatT* pFormat = NULL;
    Field             image = NULL;

    /*
     * get host and window name from display string, fill in the cache id
     */
    if (!(pFormat = _tdmParseDisplayString (where, &cacheId)))
        goto error;

    /*
     * validate the display string
     */
    if (!(_validateDisplayString(pFormat, 1)))
        goto error ;

    /*
     * Get a pointer to the global data
     */
    cacheObject = (Private) DXGetCacheEntry(cacheId, 0, 0);
    if (! cacheObject) {
        DXSetError(ERROR_BAD_PARAMETER,
                   "window matching \"%s\" not found", where);
        goto error;
    } else {
        globals = (tdmChildGlobalP) DXGetPrivateData(cacheObject) ;
        image = _dxfCaptureHardwareImage(globals);
        if (! image)
            goto error;
    }


error:
    if (pFormat)
        _dxfDeleteParsedDisplayString(pFormat);

    if (cacheId)
        tdmFree(cacheId);

    /*
     * delete the working reference 
     */
    if(cacheObject)
        DXDelete((Pointer)cacheObject) ;

    return (dxObject)image;
}
Ejemplo n.º 13
0
void
_dxfDestroyRenderModule(tdmChildGlobalP globals)
{
    DEFGLOBALDATA(globals) ;
    if (STEREOCAMERAMODE >= 0)
        _dxfExitStereoCameraMode(globals);
    if (STEREOSYSTEMMODE >= 0)
        _dxfExitStereoSystemMode(globals);
    DXDelete(OBJECT);
    tdmFree(WHERE);
    _dxf_deleteSortList(SORTLIST);
    tdmFree(globals);
}
Ejemplo n.º 14
0
static Error
_deleteHwView(Pointer arg)
{
  viewP      vp = (viewP) arg;

  ENTRY(("_dxf_deleteView(0x%x)", arg));

  if (!vp) {
    EXIT(("ERROR: vp == NULL"));
    return ERROR;
  }

  if (vp->gather)
      DXDelete((dxObject)vp->gather);
    
  if (vp->translation)
      DXDelete((dxObject)vp->translation);

  DXFree(vp);

  EXIT(("OK"));
  return OK;
}
Ejemplo n.º 15
0
Error
m_Options(Object *in, Object *out)
{
    Object a, v;
    char *s;
    int i;

    /* check input object */
    if (!in[0]) {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	return ERROR;
    }
   
    /* create output copy */
    out[0] = DXCopy(in[0], COPY_HEADER);
    if (!out[0])
	return ERROR;

    /* arrays don't copy by default - you have to call something special
     *  to get a new copy.
     */
    if (out[0] == in[0] && DXGetObjectClass(in[0]) == CLASS_ARRAY) {
	out[0] = (Object)_dxfReallyCopyArray((Array)in[0]);
	if (!out[0])
	    return ERROR;
    }

    /* set attributes */
    for (i=0; i<PAIRS; i++) {
	a = in[2*i+1];
	v = in[2*i+2];
	if (a) {
	    if (!DXExtractString(a, &s)) {
		DXSetError(ERROR_BAD_PARAMETER, "#10200", "attribute name");
		goto error;
	    }
	    /* NB - ok for v to be NULL - this deletes the attribute */
	    if (!DXSetAttribute(out[0], s, v)) 
		goto error;
	}
    }
    
    return OK;

error:
    if (out[0] != in[0])
	DXDelete(out[0]);
    out[0] = NULL;
    return ERROR;
}
Ejemplo n.º 16
0
/*
 * Module interface to look up entries in the cache.  The pointer returned
 * is the pointer supplied to DXCacheInsert when the entry was inserted.
 */
Error
DXCacheSearch(char *id, Pointer *data)
{
    Object o;

    *data = NULL;

    o = DXGetCacheEntry(id, 0, 0);
    if (o)
	*data = DXGetPrivateData((Private)o);
    DXDelete (o);

    return(OK);
}
Ejemplo n.º 17
0
static void
CaptionEndMode(void *data)
{
    CaptionData sdata = (CaptionData)data;

    /*
     * Clean up
     */
    if (sdata)
    {
	if (sdata->obj)
	    DXDelete(sdata->obj);
    }

    DXFree(data);
}
Ejemplo n.º 18
0
static void
_installQMeshInfo(xfieldT *xf, QMesh qmesh)
{
    if (xf->connections)
        DXFreeArrayHandle(xf->connections);

    if (xf->connections_array)
        DXDelete((dxObject)xf->connections_array);

    xf->connections       = NULL;
    xf->connections_array = (Array)DXReference((dxObject)qmesh->connectionArray);
    xf->nconnections      = qmesh->nconnections;
    xf->meshes            = (Array)DXReference((dxObject)qmesh->meshArray);
    xf->nmeshes           = qmesh->nmeshes;
    xf->posPerConn        = 1;
    xf->connectionType    = ct_qmesh;
}
Ejemplo n.º 19
0
static void
Slide2DSetRenderable(void *data, Object obj)
{
    Slide2DData sdata = (Slide2DData)data;
    if (sdata->obj)
	DXDelete(sdata->obj);

    /*
     * Scarf up the scene object group
     */
    if (DXGetObjectClass(obj) != CLASS_GROUP)
    {
	DXWarning("Slide2D: Object must be a group of transfomrmed objects");
	sdata->obj = NULL;
    }
    else
	sdata->obj = DXReference(obj);
}
Ejemplo n.º 20
0
static void
CaptionSetRenderable(void *data, Object obj)
{
    CaptionData sdata = (CaptionData)data;
    if (sdata->obj)
	DXDelete(sdata->obj);

    /*
     * Receive the current state of the object
     */
    if (DXGetObjectClass(obj) != CLASS_GROUP)
    {
	DXWarning("Caption: Object must be a group");
	sdata->obj = NULL;
    }
    else
	sdata->obj = DXReference(obj);
}
Ejemplo n.º 21
0
static PendingCmdList *
_dxf_newPendingCmdList()
{
    Private p;
    PendingCmdList *pjl;

    pjl = DXAllocate(sizeof(PendingCmdList));
    if (! pjl)
	return NULL;
    
    pjl->pendingCmdListSize = 0;
    pjl->pendingCmdListMax  = 10;

    pjl->pendingCmdList = DXAllocate(10*sizeof(PendingCmd));
    
    if (! pjl->pendingCmdList)
    {
	DXFree(pjl);
	return NULL;
    }

    p = DXNewPrivate((Pointer)pjl, _dxf_delete_PendingCmdList);
    if (! p)
    {
	DXFree(pjl->pendingCmdList);
	DXFree(pjl);
	return NULL;
    }

    if (! DXSetCacheEntry((Object)p, CACHE_PERMANENT, PJL_KEY, 0, 0))
    {
	DXDelete((Object)p);
	DXFree(pjl->pendingCmdList);
	DXFree(pjl);
	return NULL;
    }

    pjl->exprivate = DXReference((Object)p);

    return pjl;
}
Ejemplo n.º 22
0
static struct _table *
getTable()
{
    struct _table *table;
    Private pht = (Private)DXGetCacheEntry("__HASH_DXLInputNAMED", 0, 0);
    if (! pht)
    {
	table = (struct _table *)DXAllocate(sizeof(struct _table));
	if (! table)
	    goto error;

	table->hash = DXCreateHash(sizeof(struct _entry), hash, cmp);
	if (! table->hash)
	{
	    DXFree((Pointer)table);
	    goto error;
	}

	table->strings = NULL;
	table->owner   = DXNewPrivate((Pointer)table, delete_table);
	if (! table->owner)
	{
	    DXDestroyHash(table->hash);
	    DXFree((Pointer)table);
	    goto error;
	}

	if (! DXSetCacheEntry((Object)table->owner, CACHE_PERMANENT, "__HASH_DXLInputNAMED", 0, 0))
	{
	    DXDelete((Object)table->owner);
	    goto error;
	}

	pht = (Private)DXReference((Object)table->owner);
    }

    return (struct _table *)DXGetPrivateData(pht);

error:
    return NULL;
}
Ejemplo n.º 23
0
int
m_FaceNormals (Object *in, Object *out)
{
    out[0] = NULL;

    if (in[0] == NULL)
    {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	goto error;
    }

    out[0] = _dxfNormals(in[0], "connections");

    if (out[0] == NULL || DXGetError() != ERROR_NONE)
	goto error;
    
    return OK;

error:
    DXDelete(out[0]);
    return ERROR;
}
Ejemplo n.º 24
0
viewO
_dxf_setHwViewTranslation(viewO vo, translationO translation)
{
  viewP vp;

  if (! vo)
    return NULL;
  
  vp = (viewP)_dxf_getHwObjectData((dxObject)vo);
  if (! vp)
    return NULL;

  if (vp->translation)
  {
      DXDelete((dxObject)vp->translation);
      vp->translation = NULL;
  }

  if (translation)
      vp->translation = (translationO)DXReference((dxObject)translation);

  return vo;
}
Ejemplo n.º 25
0
viewO
_dxf_setHwViewGather(viewO vo, gatherO gather)
{
  viewP vp;

  if (! vo)
    return NULL;
  
  vp = (viewP)_dxf_getHwObjectData((dxObject)vo);
  if (! vp)
    return NULL;

  if (vp->gather)
  {
      DXDelete((dxObject)vp->gather);
      vp->gather = NULL;
  }

  if (gather)
      vp->gather = (gatherO)DXReference((dxObject)gather);

  return vo;
}
Ejemplo n.º 26
0
Error
_dxf_delete_PendingCmdList(Pointer d)
{
    int i;
    PendingCmdList *pjl = (PendingCmdList *)d;
    PendingCmd *p;

    for (i = 0, p = pjl->pendingCmdList;
		i < pjl->pendingCmdListSize; i++, p++)
    {
	DXFree(p->major);
	DXFree(p->minor);
	DXDelete((Object)p->data);

	p->major = NULL;
	p->minor = NULL;
	p->data  = NULL;
    }

    DXFree(pjl->pendingCmdList);
    DXFree(pjl);

    return OK;
}
Ejemplo n.º 27
0
Error m_SXEnum( Object *in, Object*out){
/*
*+
*  Name:
*     SXEnum

*  Purpose:
*     enumerating the positions or connections in a field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXEnum( input, name, dep );

*  Classification:
*     Realisation

*  Description:
*     The SXEnum module creates the component specified by "name", and adds
*     it to the "output" field. The values in the new component start at zero
*     and increment by one for each position or connection in the field.
*
*     The new component is in one-to-one correspondance with either the
*     "positions" or "connections" component, dependant on "dep".

*  Parameters:
*     input = field (Given)
*        input field [none]
*     name = string (Given)
*        name of component to store the enumeration ["data"]
*     dep = string (Given)
*        object to be enumerated; "positions" or "connections" ["positions"]
*     output = field (Returned)
*        output field

*  Components:
*     Adds a component with the given "name", deleting any existing
*     component. All other components are copied from the "input" field.

*  Examples:
*     In this example, the 17th frame is extracted from a data set
*     containing scattered data, and a field created holding only those
*     positions with offsets between 10 and 20.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general");
*        frame17 = Select(input,17);
*        enum = SXEnum(frame17,"index","positions");
*        marked = Mark(enum,"index");
*        included = Include(marked,10,20,1);
*        subset = Unmark(included,"index");

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     25-SEP-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/*  Local Variables. */

      char   *dep;
      char   *name;
      Object  o=NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ){
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\".");
         goto error;
      }


/*  Get a value for the "name" object. */

      if( !in[1] ){
         name = "data";

      } else {
         name = DXGetString( (String) in[1] );
         if( !name ){
            DXSetError( ERROR_BAD_PARAMETER, "unable to get string parameter \"name\".");
            goto error;
         }
      }


/*  Get a value for the "dep" object. */

      if( !in[2] ){
         dep = "positions";

      } else {
         dep = DXGetString( (String) in[2] );
         if( !dep ){
            DXSetError( ERROR_BAD_PARAMETER, "unable to get string parameter \"dep\".");
            goto error;
         }

         if( strcmp( dep, "positions" ) && strcmp( dep, "connections" ) ){
            DXSetError( ERROR_BAD_PARAMETER, "bad value (\"%s\") obtained for parameter \"dep\".",dep );
            goto error;
         }

      }


/*  Get a modifiable copy of the "input" object. */

      o = (Object) DXCopy( in[0], COPY_STRUCTURE );
      if( !o ) goto error;


/*  Enumerate it. */

      if( !DoSXEnum( o, name, dep ) ) goto error;


/*  Return the output object. */

      out[0] = o;
      return( OK );

error:
      DXDelete( o );
      return( ERROR );

}
Ejemplo n.º 28
0
/* item[n] = start + n * delta */
static 
Array MakeLinearList(Array start, Array end, int *n, Array delta)
{
    int i, j;
    Array a_start = NULL, a_end = NULL, a_delta = NULL;
    int delstart = 0, delend = 0, deldelta = 0;
    Array alist[3];
    Array output = NULL;
    int count = 1;
    int bytes;
    Type t;
    Category c;
    int rank;
    int shape[MAXSHAPE];
    int nitems;
    int i_start, i_end, i_delta;
    float f_start, f_end, f_delta, f_count;
    Pointer dp;
    int *ip;
    Object in[MAXCOMPINPUTS];  /* hardcoded in compute */
    Object out;
    String compstr = NULL;
    char cbuf[64];
    Error rc;

    /* do this or die in compute */
    for (i=0; i<MAXCOMPINPUTS; i++)
	in[i] = NULL;

    /* find common format of start, end, delta and check for 4 parms */
    i = 0;
    if (start)
	alist[i++] = start; 

    if (end)
	alist[i++] = end;

    if (delta)
	alist[i++] = delta;

    if (n) {
	count = *n;
	if (i == 3) {
	    DXWarning("too many inputs specified; ignoring delta");
	    i--;
	    delta = NULL;
	} 
    } 
    else if (i == 2)
	count = 2;

    
    if (i < 2) {
	DXSetError(ERROR_BAD_PARAMETER, 
		   "not enough inputs specified to generate a list");
	return NULL;
    }

    if (!DXQueryArrayCommonV(&t, &c, &rank, shape, i, alist)) {
	DXAddMessage("start, end and/or delta");
	return NULL;
    }

    /* shortcut the process here if the data is scalar integer or
     *  scalar float.  otherwise, if the data is vector or ubyte
     *  or whatever, fall through and use Compute so we can increment
     *  by irregular values.
     */
    if (t != TYPE_INT && t != TYPE_FLOAT)
	goto complicated;
    if (c != CATEGORY_REAL || rank != 0)
	goto complicated;


    /* compute missing value(s):
     * start = end - ((count - 1) * delta) 
     * end = start + ((count - 1) * delta) 
     * count = ((end - start) / delta) + 1 
     * delta = (end - start) / (count - 1) 
     */

    /* convert to the common format */
    if (start)
	a_start = DXArrayConvertV(start, t, c, rank, shape);
    if (end)
	a_end   = DXArrayConvertV(end,   t, c, rank, shape);
    if (delta)
	a_delta = DXArrayConvertV(delta, t, c, rank, shape);


    /* for integer, scalar lists */
    if (t == TYPE_INT) {
	if (!start) {
	    i_end = *(int *)DXGetArrayData(a_end);
	    i_delta = *(int *)DXGetArrayData(a_delta);
	    
	    i_start = i_end - ((count - 1) * i_delta);
	}

	if (!end) {
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_delta = *(int *)DXGetArrayData(a_delta);
	    
	    i_end = i_start + ((count - 1) * i_delta);
	} 

	if (!delta) {
	    /* if count == 1, generate a zero of the right type.  otherwise
	     *  divide to figure out the right delta to make count-1 steps 
	     *  between start and end.  it's count-1 because if you want
	     *  N numbers between start and end, you have N-1 increments.
	     */
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_end = *(int *)DXGetArrayData(a_end);
	    if (count == 1)
		i_delta = 0;
	    else
		i_delta = (i_end - i_start) / (count - 1);
	    
	    /* try to catch the case where delta ends up being 0 (like
	     * because the inputs are int and the count is larger than
	     * the difference between start and end).  allow it to be zero
	     * only if start == end;  i suppose if you ask for 10 things
	     * where start == end you should be able to get them.
	     */
	    if (i_delta == 0 && i_start != i_end) {
		DXSetError(ERROR_BAD_PARAMETER, 
		     "count too large to generate list between start and end");
		goto error;
	    }
	    
	}

	/* if all three arrays are there, count must be missing */
	if (i == 3) {
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_end = *(int *)DXGetArrayData(a_end);
	    i_delta = *(int *)DXGetArrayData(a_delta);

	    if (i_delta == 0)
		count = 1;
	    else {
		if ((i_end >= i_start && i_delta > 0) ||
		    (i_end < i_start && i_delta < 0))
		    count = (int)(((double)i_end-i_start) / (double)i_delta) +1;
		else {
		    if (i_delta < 0)
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be positive if start is less than end");
		    else
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be negative if end is less than start");
		    goto error;
		}
	    }
	}

	output = (Array)DXNewRegularArray(TYPE_INT, 1, count, 
					 (Pointer)&i_start, (Pointer)&i_delta);
    }

    /* for float, scalar lists */
    if (t == TYPE_FLOAT) {
	if (!start) {
	    f_end = *(float *)DXGetArrayData(a_end);
	    f_delta = *(float *)DXGetArrayData(a_delta);
	    
	    f_start = f_end - ((count - 1.0) * f_delta);
	}

	if (!end) {
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_delta = *(float *)DXGetArrayData(a_delta);
	    
	    f_end = f_start + ((count - 1.0) * f_delta);
	}

	if (!delta) {
	    /* if count == 1, generate a zero of the right type.  otherwise
	     *  divide to figure out the right delta to make count-1 steps 
	     *  between start and end.  it's count-1 because if you want
	     *  N numbers between start and end, you have N-1 increments.
	     */
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_end = *(float *)DXGetArrayData(a_end);
	    if (count == 1)
		f_delta = 0.0;
	    else 
		f_delta = (f_end - f_start) / (count - 1.0);

	    /* try to catch the case where delta ends up being 0 (like
	     * because the inputs are int and the count is larger than
	     * the difference between start and end).  allow it to be zero
	     * only if start == end;  i suppose if you ask for 10 things
	     * where start == end you should be able to get them.
	     */
	    if (f_delta == 0.0 && f_start != f_end) {
		DXSetError(ERROR_BAD_PARAMETER, 
		   "count too large to generate list between start and end");
		goto error;
	    }
	}

	/* if all three arrays are there, count must be missing */
	if (i == 3) {
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_end = *(float *)DXGetArrayData(a_end);
	    f_delta = *(float *)DXGetArrayData(a_delta);

	    if (f_delta == 0.0)
		count = 1;
	    else {
		if ((f_end >= f_start && f_delta > 0) ||
		    (f_end < f_start && f_delta < 0)) {
		    /* the intermediate float variable below is to minimize
		     * float round-off error.  if delta is 0.1 and you
		     * ask for a list between 0 and 1, it does the math in
		     * double, the delta used is actually 0.10000001, and 
		     * you get counts = 10.9999999 instead of 11.  when
		     * converted directly to int it becomes just 10 and your 
		     * list ends at 0.9 instead of 1.  
		     * math in base 2 has some problems.
		     */
		    f_count = ((f_end - f_start) / f_delta) +1;
		    count = (int)f_count;
		} else {
		    if (f_delta < 0)
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be positive if start is less than end");
		    else
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be negative if end is less than start");
		    goto error;
		}
	    }
	}

	output = (Array)DXNewRegularArray(TYPE_FLOAT, 1, count, 
					 (Pointer)&f_start, (Pointer)&f_delta);
    }
    
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    
    /* return Array */
    return output;
    

    /* input is a vector, or a data type different from int or float.
     * use compute so this code doesn't have to be replicated for each
     * different shape and type.
     */

  complicated:
    nitems = 1;
    for (j=0; j<rank; j++)
	nitems *= shape[j];

    /* compute missing value(s):
     * start = end - ((count - 1) * delta) 
     * end = start + ((count - 1) * delta) 
     * count = ((end - start) / delta) + 1 
     * delta = (end - start) / (count - 1) 
     */

    if (!start) {
	compstr = DXNewString("$0 - (($1 - 1) * $2)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)end;
	in[3] = (Object)delta;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	/* i need to explain this - it's basically so if compute was 
         * going to try to cache this, it could add a reference and
         * then later when i call delete the object won't get deleted
         * out from underneath compute.  (i know compute doesn't cache
         * things, but a different module might.)
	 */
	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	start = (Array)out;
	delstart++;
    }

    if (!end) {
	compstr = DXNewString("$0 + (($1 - 1) * $2)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)start;
	in[3] = (Object)delta;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	end = (Array)out;
	delend++;
    }

    if (!delta) {
	/* if count == 1, generate a zero of the right type.  otherwise
         *  divide to figure out the right delta to make count-1 steps 
	 *  between start and end.  it's count-1 because if you want
         *  N numbers between start and end, you have N-1 increments.
	 */
	if (count == 1)
	    compstr = DXNewString("$1 - $1");
	else
	    compstr = DXNewString("($2 - $0) / ($1 - 1)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)start;
	in[3] = (Object)end;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	delta = (Array)out;
	deldelta++;

	/* try to catch the case where delta ends up being 0 (like
	 * because the inputs are int and the count is larger than
	 * the difference between start and end).  allow it to be zero
	 * only if start == end;  i suppose if you ask for 10 things
	 * where start == end you should be able to get them.
	 */
	if (IsZero(delta) && !IsEqual(start, end)) {
	    DXSetError(ERROR_BAD_PARAMETER, 
		    "count too large to generate list between start and end");
	    goto error;
	}

    }

    /* if all three arrays are there, count must be missing */
    if (i == 3) {
	char tbuf[512];
	int firsttime = 1;
	int lastcount = 0;

	/* this loop allows us to to handle vectors or matricies as
	 *  well as scalars.   it requires that the deltas compute to
         *  a consistent count.  like start=[0 2 4], end=[4 8 16],
	 *  would work if delta=[1 2 4] but not if delta was [1 2 2].
	 */
	for (j=0; j < nitems; j++) {
	    /* i think this code only works for vectors - i'm not sure
             * what it will do with rank=2 data.
	     */

	    /* this point of this next compute expression:
	     * if the delta is 0, don't divide by zero - the count is 1. 
	     * if the end is smaller than the start, the delta has to be
             *  negative.  if it's not, return -1.  you can't generate a
             *  negative count from the equations, so this is a safe signal.
	     */
	    sprintf(tbuf, 
		    "float($2.%d) == 0.0   ? "
		    "  1 : "
		    " (  (($1.%d >= $0.%d) && ($2.%d > 0) || "
		    "     ($1.%d <  $0.%d) && ($2.%d < 0))    ? "
		    "       int(float($1.%d - $0.%d) / float($2.%d)) + 1 : "
		    "       -1 ) ", 
		    j, j, j, j, j, j, j, j, j, j);
	    compstr = DXNewString(tbuf);
	    if (!compstr)
		goto error;
	    
	    in[0] = (Object)compstr;
	    in[1] = (Object)start;
	    in[2] = (Object)end;
	    in[3] = (Object)delta;
	    
	    DXReference((Object)compstr);

	    rc = m_Compute(in, &out);
	    
	    DXDelete((Object)compstr);
	    compstr = NULL;
	    
	    if (rc == ERROR)
		goto error;
	    
	    if (!DXExtractInteger(out, &count)) {
		DXSetError(ERROR_BAD_PARAMETER, 
			   "can't compute number of items");
		goto error;
	    }

	    DXDelete((Object)out);
	    if (count == 0)
		continue;

	    if (count < 0) {
		if (IsNegative(delta))
		    DXSetError(ERROR_BAD_PARAMETER,
			 "delta must be positive if start is less than end");
		else
		    DXSetError(ERROR_BAD_PARAMETER,
			 "delta must be negative if end is less than start");
		goto error;
	    }

	    if (firsttime) {
		lastcount = count;
		firsttime = 0;
	    } else {
		if (count != lastcount) {
		    DXSetError(ERROR_BAD_PARAMETER, 
			   "inconsistent number of items required by inputs");
		    goto error;
		}
	    }
	}    
    }

    /* now have 4 consistant values - once again make sure they are
     * converted into an identical format.
     */
    a_start = DXArrayConvertV(start, t, c, rank, shape);
    a_end   = DXArrayConvertV(end,   t, c, rank, shape);
    a_delta = DXArrayConvertV(delta, t, c, rank, shape);

    /* make empty array with n items */
    output = DXNewArrayV(t, c, rank, shape);
    if (!output)
	goto error;

    if (!DXAddArrayData(output, 0, count, NULL))
	goto error;

    dp = DXGetArrayData(output);
    if (!dp)
	goto error;

    /* foreach n */
    /*  call compute to add delta */
    /*  memcpy to right offset in array */
    /* end */

    bytes = DXGetItemSize(output);

    sprintf(cbuf, "%s($0 + ($1 * $2))", TypeName(t));
    compstr = DXNewString(cbuf);
    if (!compstr)
	goto error;
    
    in[0] = (Object)compstr;
    in[1] = (Object)a_start;
    in[3] = (Object)a_delta;

    in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
    if (!in[2])
	goto error;
    if (!DXAddArrayData((Array)in[2], 0, 1, NULL))
	goto error;
    ip = (int *)DXGetArrayData((Array)in[2]);
    
    DXReference((Object)compstr);
    DXReference(in[2]);

    for (i=0; i<count; i++) {

	*ip = i;

	rc = m_Compute(in, &out);
	if (rc == ERROR)
	    goto error;

	memcpy(INCVOID(dp, bytes*i), DXGetArrayData((Array)out), bytes);
	DXDelete((Object)out);
    }

    DXDelete((Object)compstr);
    DXDelete(in[2]);
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    if (delstart)
	DXDelete((Object)start);
    if (delend)
	DXDelete((Object)end);
    if (deldelta)
	DXDelete((Object)delta);

    /* return Array */
    return output;
    
  error:
    DXDelete((Object)output);
    DXDelete((Object)compstr);
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    if (delstart)
	DXDelete((Object)start);
    if (delend)
	DXDelete((Object)end);
    if (deldelta)
	DXDelete((Object)delta);

    return NULL;
}
Ejemplo n.º 29
0
Error
_dxf_linesToPlines (xfieldT *xf)
{
  int		i;
  Line		*line = NULL,lineScratch;
  int		newEdgeI;
  Edge		edges = NULL;
  int		*polyline = NULL;
  Array		array = NULL;
  int		ptI,lastPtI;
  int		plineOffset,plineIndex;
  Edge		edgePool = NULL;
  int		nextFreeEdge = 0;

  ENTRY(("_dxf_linesToPlines(0x%x)", xf));
  
  /* allocate permanent xfield pline data of appropriate size */
  /* Allocations are a guess based on 100 lines/polyline */
  if (!(xf->meshes = DXNewArray (TYPE_INT, CATEGORY_REAL, 1, 2)) ||
      !(DXAllocateArray (xf->meshes, xf->nconnections/100)) ||

      !(array = DXNewArray (TYPE_INT, CATEGORY_REAL, 0)) ||
      !(DXAllocateArray (array, xf->nconnections+xf->nconnections/100)) ||
      !(edgePool = (Edge)DXAllocate(sizeof(EdgeT)*xf->nconnections * 2)))
    {
      PRINT(("could not allocate xfield mesh data"));
      DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;
    }

  xf->nmeshes = 0 ;

  /* get line connection info; lines will be replaced by strips */
  xf->origConnections_array = xf->connections_array ;
  xf->origNConnections = xf->nconnections;

  if(!(edges = (Edge)DXAllocateZero(xf->npositions * sizeof(EdgeT))))
    DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;
  if (!(polyline = (int *)DXAllocate((xf->nconnections+1) * sizeof(Edge)))) 
    DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;

  for(i=0;i<xf->nconnections;i++)  {
    if(xf->invCntns && !DXIsElementValid(xf->invCntns,i)) continue;
    if(!(line = DXGetArrayEntry(xf->connections,i,&lineScratch)))
      goto error;
    INSERT_EDGE(i,line->p);
    INSERT_EDGE(i,line->q);
  }

  lastPtI = 0;
  plineOffset = 0;
  plineIndex = 0;

  while (1) {
    int newPline[2] ;

    for(ptI=lastPtI;ptI<xf->npositions;ptI++) 
      if((newEdgeI = FIND_EDGE(ptI)) >= 0) break;
    
    if(ptI == xf->npositions) break;
    lastPtI = ptI;
    
    while(newEdgeI >= 0) {
      if(!(line = DXGetArrayEntry(xf->connections,newEdgeI,&lineScratch)))
	goto error;
      polyline[plineIndex++] = ptI;
      DELETE_EDGE(newEdgeI,ptI);
      ptI = OTHER_PTI(line,ptI);
      DELETE_EDGE(newEdgeI,ptI);
      newEdgeI = FIND_EDGE(ptI);
      }
    polyline[plineIndex++] = ptI;

    newPline[0] = plineOffset;
    newPline[1] = plineIndex;
#if defined(DEBUG)
    if(plineIndex >= 20)
      histogram[10]++;
    else
      histogram[plineIndex/2]++;
#endif

    /* add the pline data to the xfield */
    DXAddArrayData (xf->meshes, xf->nmeshes, 1, newPline) ;
    DXAddArrayData (array, plineOffset,
		    plineIndex, polyline) ;

    xf->nmeshes++ ;
    plineOffset += plineIndex;
    plineIndex = 0;
  }

  /* Trim extra storage allocation from arrays */
  DXTrim(xf->meshes);
  DXTrim(array);

  xf->connections_array = array;
  xf->nconnections = plineOffset + plineIndex;
  array = NULL;

  /* free old array handle and create a new one */
  if (!(DXFreeArrayHandle(xf->connections)) ||
      !(xf->connections = DXCreateArrayHandle(xf->connections_array)))
    {
      PRINT(("could not create new connections array handle"));
      DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;
    }

#if 0
  DXReference((dxObject)xf->connections_array);
  DXReference((dxObject)xf->meshes);

  /*  create a new array handleo */
  if(!(xf->connections = DXCreateArrayHandle(xf->connections_array)))
    {
      PRINT(("could not create new connections array handle"));
      DXErrorGoto(ERROR_NO_MEMORY, "#13000") ;
    }
#endif

  /* record connection info */
  xf->posPerConn = 1 ;
  xf->connectionType = ct_pline;

#if defined(DEBUG)
  for(i=0;i<11;i++)
    PRINT((" %3d",2*i));
  PRINT((" >"));
  for(i=0;i<11;i++) {
    PRINT((" %3d",histogram[i]));
    histogram[i] = 0;
  }
#endif

  DXFree(edgePool);
  DXFree(edges);
  DXFree(polyline);

  EXIT(("OK"));
  return OK ;

 error:

  if(edgePool) DXFree(edgePool);
  if(edges) DXFree(edges);
  if(polyline) DXFree(polyline);
  if(array) DXDelete((dxObject)array);
  if(xf->meshes) DXDelete((dxObject)xf->meshes);

  EXIT(("ERROR"));
  return 0 ;
}
Ejemplo n.º 30
0
/*
 * recursively generate the recipes for a node in the graph
 */
void _dxf_ExComputeRecipes(Program *p, int funcInd)
{
    gfunc	*n = FETCH_LIST(p->funcs, funcInd);
    int		i, j, size, ntags, macro_tags=0, extra_tags, async_tags=0;
    gvar	*gv;
    uint32 	tcrc;
    gvar	*out;
    uint32 	*inTags, staticTags[STATIC_TAGS];
    int		varInd, *varIndp;
    int		varInd2;
    ProgramVariable *pv, *inpv, *pv_key;
    MacroRef 	*mr;
    AsyncVars 	*avars;
    _excache    fcache;
    _excache    pvcache;
    Program     *subP=NULL;
    int  tag_changed = FALSE;
    uint32 crc = 0xFFFFFFFF;
    char 	*async_name=NULL, *name;
    int		passthru = FALSE;
    char mod_cache_str[ MAX_PATH_STR_LEN ], *mod;
    
    /*  Get module path string  */
    mod = _dxf_ExGFuncPathToCacheString( n );
    if ( strlen(mod) > sizeof(mod_cache_str)-1 )
    _dxf_ExDie("Module path is too long");
    strcpy( mod_cache_str, mod );

check_async:
    if(n->flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL)) {
        if(p->loopctl.first && (n->flags & MODULE_ASYNCLOCAL)) {
            if(strcmp(n->name, "GetLocal") == 0)
                DXReadyToRunNoExecute(mod_cache_str);
        }
        varInd = *FETCH_LIST(n->inputs, n->nin - 2);
        pv = FETCH_LIST(p->vars, varInd);
        if(!pv->gv)
            _dxf_ExDie("Cannot compute a cache tag from a NULL gvar");
        if(n->flags & MODULE_ASYNCNAMED) {
            varInd2 = *FETCH_LIST(n->inputs, n->rerun_index);
            pv_key = FETCH_LIST(p->vars, varInd2);
            if(pv_key->gv && pv_key->gv->obj) {
                if(pv->gv->obj)
                    DXDelete(pv->gv->obj);
                pv->gv->obj = DXReference(pv_key->gv->obj);    
            }
        }
        if(!pv->gv->obj)
            _dxf_ExDie("Cannot compute a cache tag from a NULL gvar");
        /* Put an extra reference on this input, we don't want this gvar
           to be deleted until the current graph finishes executing. This
           is incase the results were thrown out of cache and because of
           a switch need to run again. If this is in a loop it will get
           an extra ref each time through the loop which isn't needed but
           will get cleaned up ok in the end.
        */
        ExReference(pv->gv);
        pv->refs++;
        async_name = DXGetString((String)pv->gv->obj);
        varInd = *FETCH_LIST(n->inputs, n->nin - 1);
        pv = FETCH_LIST(p->vars, varInd);
        gv = (gvar *)_dxf_ExGlobalVariableSearch(async_name);
        if(gv) {
            if(gv != pv->gv) {
                _dxf_ExUndefineGvar(pv->gv);
                _dxf_ExDefineGvar(pv->gv, gv->obj);
            }
            ExDelete(gv);
        }
        else {
            Object value;
            value = (Object) _dxfExNewInteger (0);
            _dxf_ExDefineGvar(pv->gv, (Object)_dxfExNewInteger(0));
            _dxf_ExUpdateGlobalDict (async_name, value, 0);
        }
        /* Put an extra reference on this input, we don't want this gvar
           to be deleted until the current graph finishes executing. This
           is incase the results were thrown out of cache and because of
           a switch need to run again. If this is in a loop it will get
           an extra ref each time through the loop which isn't needed but
           will get cleaned up ok in the end.
         */
         ExReference(pv->gv);
         pv->refs++;
    }

    if(n->ftype == F_MACRO) {
        subP = n->func.subP;
        macro_tags = SIZE_LIST(subP->macros);
        async_tags = SIZE_LIST(subP->async_vars);
        extra_tags = macro_tags + async_tags;
    }
    else if(n->flags & MODULE_LOOP) {
        /* to cause the cache tag of loop modules to change even though */
        /* their inputs don't change, use the counter for the loop */
        extra_tags = 1;
    }
    else extra_tags = 0;
    ntags = n->nin+extra_tags;

    if(ntags > STATIC_TAGS)
        inTags = (uint32 *)DXAllocate(ntags*sizeof(uint32));
    else inTags = staticTags;

    /* add the crc of all of the module inputs to the total crc */
    for (i = 0; i < SIZE_LIST(n->inputs); i++)
    {
	varIndp = FETCH_LIST(n->inputs, i);
        if(varIndp == NULL)
            _dxf_ExDie("Executive Inconsistency: _dxf_ExComputeRecipes");
        varInd = *varIndp;
      
        inTags[i] = computeRecipe(p, varInd);
	ExDebug ("1", "Cache value for input %s.%d = 0x%08x ",
			    n->name, i, inTags[i]);
    }

    if(n->ftype == F_MACRO) {
        for (j = 0; j < macro_tags; j++, i++)
        {
            crc = 0xFFFFFFFF;
            mr = FETCH_LIST(subP->macros, j);
            inTags[i] = _dxf_ExCRCInt(crc, mr->index);
        }
        for (j = 0; j < async_tags; j++, i++) {
            avars = FETCH_LIST(subP->async_vars, j);
            pv = FETCH_LIST(p->vars, avars->nameindx);
            if(!pv->gv || !pv->gv->obj)
                _dxf_ExDie("Cannot compute a cache tag from a NULL async name");
            name = DXGetString((String)pv->gv->obj);
            pv = FETCH_LIST(p->vars, avars->valueindx);
            gv = (gvar *)_dxf_ExGlobalVariableSearch(name);
            if(gv) {
                if(gv != pv->gv) {
                    _dxf_ExUndefineGvar(pv->gv);
                    _dxf_ExDefineGvar(pv->gv, gv->obj);
                }
                ExDelete(gv);
            }
            else {
                Object value;
                value = (Object) _dxfExNewInteger (0);
                _dxf_ExDefineGvar(pv->gv, (Object)_dxfExNewInteger(0));
                _dxf_ExUpdateGlobalDict (name, value, 0);
            }
            inTags[i] = computeRecipe(p, avars->valueindx);
        }
    }
    else if(n->flags & MODULE_LOOP) {
        /* to cause the cache tag of loop modules to change even though */
        /* their inputs don't change, use the counter for the loop */
        crc = 0xFFFFFFFF;
        inTags[i] = _dxf_ExCRCInt(crc, p->loopctl.counter);
    }

    if((n->flags & MODULE_PASSTHRU) && (n->nin == n->nout+1))
        passthru = TRUE;
        
    if(n->flags & (MODULE_CONTAINS_STATE | MODULE_CHANGES_STATE))
    {
        Object new_tag_obj, old_tag_obj;
        uint32 oldtag, newtag;

        newtag = _dxf_ExGenCacheTag (n->name,0,ntags,inTags);
        new_tag_obj = (Object)DXMakeInteger(newtag);
        old_tag_obj = DXGetCacheEntry(mod_cache_str, ntags, 0);
        if(!old_tag_obj) {
            DXSetCacheEntry(new_tag_obj, CACHE_PERMANENT, mod_cache_str, ntags, 0);
        }
        else {
            /* we don't want an extra reference on this */
            DXDelete(old_tag_obj); 
            if(!DXExtractInteger(old_tag_obj, (int *)&oldtag))
                oldtag = 0;
            /* this means we just caused a DXReadyToRun so we know */
            /* this macro will run this time, save the new cache tag */
            if(oldtag == 0) {
                DXSetCacheEntry(new_tag_obj,CACHE_PERMANENT,mod_cache_str,ntags,0);
                DXDelete(old_tag_obj);
            }
            else if(oldtag != newtag) {
                /* An input has changed since last time, we need to */ 
                /* cause execution of this macro and we need to recompute */
                /* the cache tag. */
                DXReadyToRunNoExecute(async_name);
                DXDelete(new_tag_obj);
                new_tag_obj = (Object)DXMakeInteger(0);
                DXSetCacheEntry(new_tag_obj,CACHE_PERMANENT,mod_cache_str,ntags,0);
                DXDelete(old_tag_obj);
                goto check_async;
            }
            else DXDelete(new_tag_obj);
        }
    }

    /* generate the recipes for all of the outputs from this module */
    /* Update the pathtag table if module cache attribute is "cache last" */
    n->tag_changed = FALSE;
    for (i = 0; i < SIZE_LIST(n->outputs); i++)
    {
	varIndp = FETCH_LIST(n->outputs, i);
        if(varIndp == NULL)
            _dxf_ExDie("Executive Inconsistency: _dxf_ExComputeRecipes");
        varInd = *varIndp;
	pv = FETCH_LIST(p->vars, varInd);
        pv->is_output = TRUE;
	out = pv->gv;

	if (out->reccrc == 0 || 
	    (n->required != -1 && (!IsSwitch(n) || !IsFastSwitch(n)))) {
            /* This code is currently just intended for macrostart */
            if(passthru) {
	        varInd2 = *FETCH_LIST(n->inputs, i+1);
		if (varInd2 != -1) {
                    inpv = FETCH_LIST(p->vars, varInd2);
                    tcrc = inpv->gv->reccrc;
		} else
	            tcrc = _dxf_ExGenCacheTag (n->name,i,n->nin+extra_tags,inTags);
            }
            else
	        tcrc = _dxf_ExGenCacheTag (n->name,i,n->nin+extra_tags,inTags);
            if(out->reccrc != 0 && tcrc != out->reccrc)
                _dxf_ExUndefineGvar(out);
            pv->reccrc = out->reccrc = tcrc;
	    /* make process group name part of cache tag */
	    if(n->procgroupid) {
		size = strlen (n->procgroupid);
		out->reccrc = EXTAG(_dxf_ExCRCByteV(out->reccrc & 0x7fffffff,
		    (unsigned char *) n->procgroupid, 1, size));
	    }
	    ExDebug ("1", "Cache value for %s.%d = 0x%08x ",
			    n->name, i, out->reccrc);
	}
        
        pvcache = pv->excache;
        fcache  = n->excache;
       
        if((n->flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL)) && 
           (pvcache == CACHE_ALL)) 
            pvcache = pv->excache = CACHE_LAST;
  
        /* I don't think we allow the user to turn off cacheing for */
        /* macros that have state in them. */
        if(n->flags & MODULE_CHANGES_STATE)
            pvcache = pv->excache = CACHE_LAST_PERM;
        if(n->flags & MODULE_CONTAINS_STATE)
            pvcache = pv->excache = CACHE_LAST;

        /* object lvl cache attribute overrides function lvl cache attribute */ 
        
        if (pvcache == CACHE_LAST || pvcache == CACHE_LAST_PERM) 
            tag_changed = _dxf_ExManageCacheTable(&n->mod_path, out->reccrc, i);
        else 
            if(fcache == CACHE_LAST && !pv->cacheattr) 
                tag_changed = _dxf_ExManageCacheTable(&n->mod_path, out->reccrc, i);
        n->tag_changed = tag_changed;
    }

    if(n->nout == 0 && !(n->flags & MODULE_SIDE_EFFECT)) {
        tcrc = _dxf_ExGenCacheTag (n->name, 0, n->nin+extra_tags, inTags);
        n->tag_changed = _dxf_ExManageCacheTable(&n->mod_path, tcrc, 0);
    }

    if(ntags > STATIC_TAGS)
        DXFree(inTags);
}