/***********************************************************************/ /* 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" */ /***********************************************************************/ /* * $Header: /home/gda/dxcvs/dx/src/exec/dxmods/transpose.c,v 1.3 1999/05/10 15:45:32 gda Exp $ */ #include #include #include static Object Object_Transpose(Object o, int num, int *dimlist); static Field Field_Transpose(Field f, int num, int *dimlist); static Array Item_Transpose(Array a, int num, int *dimlist, char *comp); static Array Connect_Transpose(Array a, int num, char *element); #define STR(x) (Object)DXNewString(x) #define MAXRANK 16 #define MAXSHAPE 128 #define PARALLEL 1 #if PARALLEL static Field Transpose_Wrapper(Field, char *, int); struct argblk { int ndim; int dim[MAXRANK]; }; #endif #define is_empty(o) ((DXGetObjectClass(o)==CLASS_FIELD) && DXEmptyField((Field)o)) /* 0 = input * 1 = new dimension order * * 0 = output */ int m_Transpose(Object *in, Object *out) { int i, ndim; char cdim, *cp; int dim[MAXRANK]; if(!in[0]) { DXSetError(ERROR_BAD_PARAMETER, "#10000", "input"); return ERROR; } if(!in[1] || is_empty(in[0])) { out[0] = in[0]; return OK; } /* input can either be a list of integers, or a list of strings. */ if (DXQueryParameter(in[1], TYPE_STRING, 1, &ndim)) { /* list of strings - since there isn't a get-number-of-strings call, * check first to be sure there aren't too many, and then loop * until there aren't any more. */ if(DXExtractNthString(in[1], MAXRANK, &cp)) { DXSetError(ERROR_BAD_PARAMETER, "bad number of dimensions in list"); return ERROR; } for(i=0; i 'z') { DXSetError(ERROR_BAD_PARAMETER, "bad dimension letter"); return ERROR; } dim[i] = (int)(cdim - 'x'); } } ndim = i; if(ndim <= 1 || ndim > MAXRANK) { DXSetError(ERROR_BAD_PARAMETER, "bad number of dimensions in list"); return ERROR; } } else if(DXQueryParameter(in[1], TYPE_INT, 1, &ndim)) { /* list of ints */ if(ndim <= 1 || ndim > MAXRANK) { DXSetError(ERROR_BAD_PARAMETER, "bad number of dimensions in list"); return ERROR; } if(!DXExtractParameter(in[1], TYPE_INT, 1, ndim, (Pointer)dim)) { DXSetError(ERROR_BAD_PARAMETER, "bad dimension list"); return ERROR; } } else { /* neither integers or strings */ DXSetError(ERROR_BAD_PARAMETER, "bad dimension list"); return ERROR; } #if PARALLEL { struct argblk argblk; int i; argblk.ndim = ndim; for (i=0; indim, ((struct argblk *)argblk)->dim); } #endif /* */ static Object Object_Transpose(Object o, int num, int *dims) { Object subo; char *name; int i; switch(DXGetObjectClass(o)) { case CLASS_GROUP: /* for each member */ for(i=0; subo = DXGetEnumeratedMember((Group)o, i, &name); i++) { if(!Object_Transpose(subo, num, dims)) return NULL; } break; case CLASS_FIELD: #if ! PARALLEL if(DXEmptyField((Field)o)) break; #else if(DXEmptyField((Field)o)) return NULL; o = DXCopy(o, COPY_STRUCTURE); if(!o) return NULL; #endif if (!Field_Transpose((Field)o, num, dims)) { DXDelete(o); o = NULL; } break; default: /* ignore things we don't understand */ break; } return o; } /* */ static Field Field_Transpose(Field f, int num, int *dims) { Object newo, subo; char *name, *attr; int i, j, n, nitems, rank; int inverted = 0; int ndims[MAXRANK]; int pcounts[MAXRANK], ccounts[MAXRANK]; float origins[MAXRANK], norigins[MAXRANK]; float deltas[MAXRANK*MAXRANK], ndeltas[MAXRANK*MAXRANK]; /* transpose positions. */ subo = DXGetComponentValue(f, "positions"); if(!subo) { DXSetError(ERROR_MISSING_DATA, "#10240", "positions"); return ERROR; } if(!DXTypeCheckV((Array)subo, TYPE_FLOAT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "positions must be type float, rank 1"); return NULL; } /* make sure all the dims are valid before proceeding */ DXGetArrayInfo((Array)subo, &nitems, NULL, NULL, &rank, pcounts); if(rank != 1) { if(rank == 0) pcounts[0] = 1; /* rank 0 == rank 1, shape 1 */ else DXErrorReturn(ERROR_INVALID_DATA, "bad position component"); } if(num != pcounts[0]) { DXSetError(ERROR_BAD_PARAMETER, "#11365", num, pcounts[0]); return NULL; } /* initialize a use-counts list. in the second loop, if we find the * same dimension more than once in the list, it's an error. */ for(i=0; i= num) { DXSetError(ERROR_BAD_PARAMETER, "#11361", dims[i], "input", num-1); return NULL; } /* duplicates? */ if(++ndims[dims[i]] > 1) { DXSetError(ERROR_BAD_PARAMETER, "dimension %d appears more than once in list", dims[i]); return NULL; } } /* dim list should be ok. now rearrange positions */ if(DXQueryGridPositions((Array)subo, &n, pcounts, origins, deltas)) { /* regular grid */ for(i=0; i1, and call item_tr() */ ndims[0] = 1; ndims[1] = 0; for(i=2; i