/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ /* if all points in generic positions arrays are to be compared (as * opposed to just the number of items in the positions arrays), uncomment * the following #defines. */ /* #define CHECK_ANY_POSITIONS */ /* #define CHECK_ALL_POSITIONS */ #include #include #include #include "_compute.h" /* * _ComputeInitInputs initialize the set of inputs for compute */ void _dxfComputeInitInputs(CompInput *inputs) { int i; for (i = 0; i < MAX_INPUTS; ++i) { inputs[i].used = 0; } } static int ComparePositions(Array master, Array checked) { Class masterClass; Class checkedClass; int masterN; int checkedN; int *masterCounts = NULL; int *checkedCounts = NULL; float *masterOrigin = NULL; float *checkedOrigin = NULL; float *masterDeltas = NULL; float *checkedDeltas = NULL; MetaType masterType; MetaType checkedType; Pointer masterData; Pointer checkedData; int status; int i, j; int numBasic; if (master == checked) return (OK); if (master == NULL || checked == NULL) return (ERROR); masterClass = DXGetArrayClass (master); checkedClass = DXGetArrayClass (checked); if (masterClass != checkedClass) return (ERROR); switch (masterClass) { case CLASS_ARRAY: default: if (DXGetArrayInfo (master, &masterType.items, &masterType.type, &masterType.category, &masterType.rank, masterType.shape) == NULL) { return (ERROR); } if (DXGetArrayInfo (checked, &checkedType.items, &checkedType.type, &checkedType.category, &checkedType.rank, checkedType.shape) == NULL) { return (ERROR); } if ( masterType.items != checkedType.items || masterType.type != checkedType.type || masterType.category != checkedType.category || masterType.rank != checkedType.rank) { return (ERROR); } #ifdef CHECK_ALL_POSITIONS numBasic = 1; #endif for (i = 0; i < masterType.rank; ++i) { if (masterType.shape[i] != checkedType.shape[i]) { return (ERROR); } #ifdef CHECK_ALL_POSITIONS numBasic *= masterType.shape[i]; #endif } #ifdef CHECK_ALL_POSITIONS masterData = DXGetArrayData (master); if (masterData == NULL) { return (ERROR); } checkedData = DXGetArrayData (checked); if (checkedData == NULL) { return (ERROR); } status = bcmp (masterData, checkedData, masterType.items * TypeSize (masterType.type) * CategorySize (masterType.category) * numBasic) == 0? OK: ERROR; #else status = OK; #endif break; case CLASS_CONSTANTARRAY: if (DXGetArrayInfo (master, &masterType.items, &masterType.type, &masterType.category, &masterType.rank, masterType.shape) == NULL) { return (ERROR); } if (DXGetArrayInfo (checked, &checkedType.items, &checkedType.type, &checkedType.category, &checkedType.rank, checkedType.shape) == NULL) { return (ERROR); } if ( masterType.items != checkedType.items || masterType.type != checkedType.type || masterType.category != checkedType.category || masterType.rank != checkedType.rank) { return (ERROR); } for (i = 0; i < masterType.rank; ++i) { if (masterType.shape[i] != checkedType.shape[i]) { return (ERROR); } } masterData = DXGetConstantArrayData(master); checkedData = DXGetConstantArrayData(checked); if (bcmp(masterData, checkedData, DXGetItemSize(master)) == 0) status = OK; else status = ERROR; break; case CLASS_REGULARARRAY: case CLASS_PRODUCTARRAY: case CLASS_PATHARRAY: case CLASS_MESHARRAY: if (DXQueryGridPositions (master, &masterN, NULL, NULL, NULL) == NULL) { DXSetError (ERROR_INTERNAL, "ComparePositions, %d: Can't get regular array data", __LINE__); status = ERROR; break; } if (DXQueryGridPositions (checked, &checkedN, NULL, NULL, NULL) == NULL) { DXSetError (ERROR_INTERNAL, "ComparePositions, %d: Can't get regular array data", __LINE__); status = ERROR; break; } if (masterN != checkedN) { status = ERROR; break; } if ((masterCounts = (int *) DXAllocateLocal (masterN * sizeof (int))) == NULL) { status = ERROR; break; } if ((checkedCounts = (int *) DXAllocateLocal (masterN * sizeof (int))) == NULL) { status = ERROR; break; } if ((masterOrigin = (float *) DXAllocateLocal (masterN * sizeof (float))) == NULL) { status = ERROR; break; } if ((checkedOrigin = (float *) DXAllocateLocal (masterN * sizeof (float))) == NULL) { status = ERROR; break; } if ((masterDeltas = (float *) DXAllocateLocal (masterN * masterN * sizeof (float))) == NULL) { status = ERROR; break; } if ((checkedDeltas = (float *) DXAllocateLocal (masterN * masterN * sizeof (float))) == NULL) { status = ERROR; break; } if (DXQueryGridPositions (master, &masterN, masterCounts, masterOrigin, masterDeltas) == NULL) { DXSetError (ERROR_INTERNAL, "ComparePositions, %d: Can't get regular array data", __LINE__); status = ERROR; break; } if (DXQueryGridPositions (checked, &checkedN, checkedCounts, checkedOrigin, checkedDeltas) == NULL) { DXSetError (ERROR_INTERNAL, "ComparePositions, %d: Can't get regular array data", __LINE__); status = ERROR; break; } status = OK; for (i = 0; i < masterN && status == OK; ++i) { if (masterCounts[i] != checkedCounts[i] || masterOrigin[i] != checkedOrigin[i]) { status = ERROR; } for (j = 0; j < masterN && status == OK; ++j) { if (masterDeltas[i * masterN + j] != checkedDeltas[i * masterN + j]) { status = ERROR; } } } break; } DXFree ((Pointer) masterCounts); DXFree ((Pointer) checkedCounts); DXFree ((Pointer) masterOrigin); DXFree ((Pointer) checkedOrigin); DXFree ((Pointer) masterDeltas); DXFree ((Pointer) checkedDeltas); return (status); } /* * SaveObjStruct records the structure of the output object, and returns * a tree of ObjStructs. O should be a copy of the first input that is * not a trivial (unit length) array. */ static ObjStruct * SaveObjStruct (Object o, int *id) { ObjStruct *res = (ObjStruct *) DXAllocateZero(sizeof (ObjStruct)); ObjStruct *so; /* Subobject */ int memInd; Object mem; Array a; ObjStruct **lastSubObjPtr; if (res) { res->output = o; res->members = NULL; res->parseTree = NULL; switch (res->class = DXGetObjectClass (o)) { case CLASS_MIN: /* o was null */ res->class = CLASS_ARRAY; res->metaType.items = 1; break; case CLASS_ARRAY: DXGetArrayInfo ((Array)o, &res->metaType.items, &res->metaType.type, &res->metaType.category, &res->metaType.rank, res->metaType.shape); res->metaType.id = (*id)++; break; case CLASS_STRING: res->metaType.items = 1; res->metaType.type = TYPE_STRING; res->metaType.category = CATEGORY_REAL; res->metaType.rank = 1; res->metaType.shape[0] = strlen(DXGetString((String) o))+1; res->metaType.id = (*id)++; break; case CLASS_FIELD: if ((a = (Array) DXGetComponentValue((Field)o, "data")) == NULL) a = (Array) DXGetComponentValue((Field)o, "positions"); if (a == NULL) { res->metaType.items = 0; res->metaType.type = TYPE_FLOAT; res->metaType.category = CATEGORY_REAL; res->metaType.rank = 1; res->metaType.shape[0] = 1; } else { DXGetArrayInfo (a, &res->metaType.items, &res->metaType.type, &res->metaType.category, &res->metaType.rank, res->metaType.shape); } res->metaType.id = (*id)++; break; case CLASS_GROUP: /* Append each member 'so' to the end of res's member * list */ res->subClass = DXGetGroupClass((Group)o); lastSubObjPtr = &res->members; for (memInd = 0; (mem = DXGetEnumeratedMember ((Group)o, memInd, (char **)NULL)) != NULL; ++memInd) { so = SaveObjStruct ((Object)mem, id); if (!so) goto SaveObjError; so->next = NULL; *lastSubObjPtr = so; lastSubObjPtr = &(so->next); } break; case CLASS_XFORM: if (DXGetXformInfo((Xform)o, &mem, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13210"); goto SaveObjError; } res->members = SaveObjStruct ((Object)mem, id); if (!res->members) goto SaveObjError; res->members->next = NULL; break; case CLASS_SCREEN: if (DXGetScreenInfo((Screen)o, &mem, NULL, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13240"); goto SaveObjError; } res->members = SaveObjStruct ((Object)mem, id); if (!res->members) goto SaveObjError; res->members->next = NULL; break; case CLASS_CLIPPED: if (DXGetClippedInfo((Clipped)o, &mem, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13220"); goto SaveObjError; } res->members = SaveObjStruct ((Object)mem, id); if (!res->members) goto SaveObjError; res->members->next = NULL; break; default: DXSetError (ERROR_BAD_CLASS, "#10370", "input", "Array, Field, Group, Transform, Screen, or Clipped"); goto SaveObjError; } } return (res); SaveObjError: DXFree((Pointer)res); return(NULL); } static int MatchObjStruct (ObjStruct *master, Object o, int inputNum) { ObjStruct *child; int memInd; Object mem; int items; Array a; Class class; Array positions; Array masterPositions; if (master) { master->inputs[inputNum] = o; /* Classes must match, EXCEPT unit length arrays match anything */ if (master->class != (class = DXGetObjectClass (o))) { if (class == CLASS_ARRAY) { DXGetArrayInfo ((Array) o, &items, NULL, NULL, NULL, NULL); if (items != 1) { DXErrorReturn (ERROR_BAD_CLASS, "#11830"); } } else { if (class != CLASS_STRING) DXErrorReturn (ERROR_BAD_CLASS, "#11830"); } } /* Perform class type checking */ switch (master->class) { case CLASS_GROUP: /* if the tested class is an array and we're here, the array * is unit lenght, and should be matched with all subobjects */ if (class == CLASS_ARRAY) { for (child = master->members; child != NULL; child = child->next) { if (!MatchObjStruct (child, o, inputNum)) { return (ERROR); } } } else { if (master->subClass != DXGetGroupClass((Group)o)) { DXErrorReturn (ERROR_BAD_CLASS, "#11830"); } for (memInd = 0, child = master->members, (mem = DXGetEnumeratedMember ((Group)o, memInd, NULL)); child && mem; ++memInd, child = child->next, (mem = DXGetEnumeratedMember ((Group)o, memInd, NULL))){ if (!MatchObjStruct (child, mem, inputNum)) { return (ERROR); } } if (child != NULL || mem != NULL) { DXErrorReturn (ERROR_BAD_PARAMETER, "#11830"); } } break; case CLASS_FIELD: /* if the tested class is an array and we're here, the array * is unit lenght, and should be matched with all subobjects */ if (class != CLASS_ARRAY) { #ifdef CHECK_ANY_POSITIONS positions = (Array)DXGetComponentValue ((Field)o, "positions"); masterPositions = (Array)DXGetComponentValue ((Field)master->output, "positions"); if (ComparePositions (masterPositions, positions) == ERROR) { DXWarning ("#11840"); } #endif a = (Array) DXGetComponentValue ((Field) o, "data"); if (a == NULL) { if (master->metaType.items != 0) { DXSetError(ERROR_BAD_PARAMETER, "#10240", "data"); return ERROR; } } else { DXGetArrayInfo (a, &items, NULL, NULL, NULL, NULL); if (items != master->metaType.items) { DXErrorReturn (ERROR_BAD_PARAMETER, "#11820"); } } } break; case CLASS_ARRAY: DXGetArrayInfo ((Array) o, &items, NULL, NULL, NULL, NULL); /* unit length arrays match with anything */ if (items != 1) { if (items != master->metaType.items) { DXErrorReturn (ERROR_BAD_PARAMETER, "#11820"); } } break; case CLASS_STRING: break; case CLASS_XFORM: if (class != CLASS_ARRAY) { if (DXGetXformInfo((Xform)o, &mem, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13210"); return ERROR; } } else mem = o; if (!MatchObjStruct(master->members, mem, inputNum)) { return ERROR; } break; case CLASS_SCREEN: if (class != CLASS_ARRAY) { if (DXGetScreenInfo((Screen)o, &mem, NULL, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13240"); return ERROR; } } else mem = o; if (!MatchObjStruct(master->members, mem, inputNum)) { return ERROR; } break; case CLASS_CLIPPED: if (class != CLASS_ARRAY) { if (DXGetClippedInfo((Clipped)o, &mem, NULL) == NULL) { DXSetError (ERROR_BAD_PARAMETER, "#13220"); return ERROR; } } else mem = o; if (!MatchObjStruct(master->members, mem, inputNum)) { return ERROR; } break; default: DXSetError (ERROR_BAD_CLASS, "#10370", "input", "Array, Field, Group, Transform, Screen, or Clipped"); return ERROR; } } return (OK); } void _dxfComputeFreeObjStruct (ObjStruct *os) { ObjStruct *subObj; ObjStruct *nextObj; for (subObj = os->members; subObj != NULL; subObj = nextObj) { nextObj = subObj->next; _dxfComputeFreeObjStruct (subObj); } if (os->parseTree != NULL) { _dxfComputeFreeTree (os->parseTree); } DXFree ((Pointer)os); } /* * _ComputeGetInputs sets up the inputs array, which contains the type of each * input, and returns an ObjStruct tree which contains the output object * and pairings for actually doing work. */ ObjStruct * _dxfComputeGetInputs(Object *in, CompInput *inputs) { int i; ObjStruct *res = NULL; Object outputObject; int masterIndex; int masterItems; int id = 0; /* Find the first input that is a non-trivial (unit length) array, * and set up a copy as the output array */ for (masterIndex = i = 0; i < MAX_INPUTS; ++i) { if (in[i] == NULL) { continue; } if (DXGetObjectClass(in[i]) == CLASS_ARRAY) { DXGetArrayInfo ((Array)in[i], &masterItems, NULL, NULL, NULL, NULL); if (masterItems == 1) { continue; } } masterIndex = i; break; } if (in[masterIndex] == NULL || DXGetObjectClass(in[masterIndex]) == CLASS_ARRAY) { outputObject = in[masterIndex]; } else { outputObject = DXCopy (in[masterIndex], COPY_STRUCTURE); if (outputObject == NULL) return (NULL); } res = SaveObjStruct (outputObject, &id); if (!res) return (NULL); /* Now, collect the type information and verify the structure of all * inputs. */ for (i = 0; i < MAX_INPUTS; ++i) { if (inputs[i].used && in[i]) { inputs[i].class = DXGetObjectClass (in[i]); inputs[i].object = in[i]; /* Get type info */ if (MatchObjStruct (res, in[i], i) == ERROR) { if (i != masterIndex) { DXAddMessage ("Input %d not matching the master (input %d)", i, masterIndex); } _dxfComputeFreeObjStruct(res); return (NULL); } } else if (inputs[i].used) { DXSetError (ERROR_BAD_PARAMETER, "#11810", i); _dxfComputeFreeObjStruct(res); return (NULL); } } return (res); } #ifdef COMP_DEBUG static char * ClassString (Class class) { char *cs; switch (class) { case CLASS_ARRAY: cs = "CLASS_ARRAY"; break; case CLASS_FIELD: cs = "CLASS_FIELD"; break; case CLASS_GROUP: cs = "CLASS_GROUP"; break; default: cs = "Unknown Class"; break; } return (cs); } static void DumpObjStruct (ObjStruct *os, int indent) { ObjStruct *subObj; static char *spaces = " "; char *ind = spaces + (strlen (spaces) - indent); int i; /* Print stuff about the os */ if (os->class != CLASS_GROUP || os->subClass != CLASS_GROUP) { DXDebug ("C", "%sPseudo-leaf node 0x%08x, class = %d", ind, os, os->class); DXDebug ("C", " items = %d", os->metaType.items); DXDebug ("C", " type = %d", os->metaType.type); DXDebug ("C", " category = %d", os->metaType.category); DXDebug ("C", " rank = %d [", os->metaType.rank); for (i = 0; i < os->metaType.rank; ++i) { DXDebug ("C", " %d", os->metaType.shape[i]); } DXDebug ("C", "]"); } else { DXDebug ("C", "%sHeterogeneous Group node 0x%08x", ind, os); } /* Recurse */ for (subObj = os->members; subObj != NULL; subObj = subObj->next) { DumpObjStruct (subObj, indent + 4); } } void _dxfComputeDumpInputs(CompInput *inputs, ObjStruct *os) { int i; char *cs; for (i = 0; i < MAX_INPUTS; ++i) { if (inputs[i].used) { cs = ClassString(inputs[i].class); DXDebug ("C", "Input[%d] (%s)", i, cs); } } DXDebug ("C", "Object Structure Tree"); DumpObjStruct (os, 0); } #endif