/***********************************************************************/ /* 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" */ /***********************************************************************/ #include #include #include #include "arrayClass.h" /* * size multipliers for type, category */ /* XXX */ int DXTypeSize(Type t) { switch (t) { case TYPE_BYTE: return sizeof(byte); case TYPE_UBYTE: return sizeof(ubyte); case TYPE_SHORT: return sizeof(short); case TYPE_USHORT: return sizeof(ushort); case TYPE_INT: return sizeof(int); case TYPE_UINT: return sizeof(uint); case TYPE_HYPER: return 8; case TYPE_FLOAT: return sizeof(float); case TYPE_DOUBLE: return sizeof(double); case TYPE_STRING: return sizeof(char); default: return DXSetError(ERROR_BAD_PARAMETER, "unknown Type %d", t); } } int DXCategorySize(Category category) { switch(category) { case CATEGORY_REAL: return 1; case CATEGORY_COMPLEX: return 2; case CATEGORY_QUATERNION: return 4; default: return DXSetError(ERROR_BAD_PARAMETER, "unknown Category %d", category); } } /* * new array, shape specified as a vector */ Array _dxf_NewArrayV(Type type, Category category, int rank, int *shape, struct array_class *class) { int i; Array a = (Array) _dxf_NewObject((struct object_class *)class); if (!a) return NULL; /* specified info */ a->type = type; a->category = category; a->rank = rank; if (shape && rank!=0) { a->shape = rank>NLSHAPE? (int*)DXAllocate(rank*sizeof(*shape)) : a->lshape; if (!a->shape) return NULL; for (i=0; ishape[i] = shape[i]; } else if (rank != 0) { DXSetError(ERROR_BAD_PARAMETER, "rank=%d but shape was not specified in DXNewArray", rank); return NULL; } else a->shape = NULL; /* size is derived */ a->size = DXTypeSize(type) * DXCategorySize(category); if (!a->size) return NULL; for (i=0; isize *= shape[i]; if (!a->size) DXErrorReturn(ERROR_BAD_PARAMETER, "extent specified as 0 in DXNewArray"); a->items = 0; a->data = NULL; DXcreate_lock(&a->inprogress, "in progress"); return a; } Array DXNewArrayV(Type type, Category category, int rank, int *shape) { return _dxf_NewArrayV(type, category, rank, shape, &_dxdarray_class); } Array DXNewArray(Type type, Category category, int rank, ...) { int shape[100]; int i; va_list arg; ASSERT(rank<100); /* collect args */ va_start(arg,rank); for (i=0; iitems; if (type) *type = a->type; if (category) *category = a->category; if (rank) *rank = a->rank; if (shape) for (i=0; irank; i++) shape[i] = a->shape[i]; return a; } Object _dxfArray_GetType(Array a, Type *t, Category *c, int *rank, int *shape) { int i; if (t) *t = a->type; if (c) *c = a->category; if (rank) *rank = a->rank; if (shape) for (i=0; irank; i++) shape[i] = a->shape[i]; return (Object) a; } int DXGetItemSize(Array a) { CHECK(a, CLASS_ARRAY); return a->size; } Array DXTypeCheckV(Array a, Type type, Category category, int rank, int *shape) { Type t; Category c; int i, r, s[100]; ASSERT(rank<100); if (!DXGetArrayInfo(a, NULL, &t, &c, &r, NULL)) return NULL; if (t!=type || c!=category || r!=rank) return NULL; if (!DXGetArrayInfo(a, NULL, NULL, NULL, NULL, s)) return NULL; if (shape) for (i=0; idata) DXAllocateArray(a, 0); return a->data; } Pointer DXGetArrayDataLocal(Array a) { int n; Pointer data, local; CHECK(a, CLASS_ARRAY); data = DXGetArrayData(a); #if DXD_HAS_LOCAL_MEMORY if (!data) return NULL; /* XXX - copy, record local reference */ n = a->size * a->items; local = DXAllocateLocal(n); if (!local) { DXResetError(); DXWarning("no room for array of %d bytes in local memory", n); return data; } memcpy(local, data, n); return local; #else return data; #endif } Array DXFreeArrayDataLocal(Array a, Pointer data) { CHECK(a, CLASS_ARRAY); #if DXD_HAS_LOCAL_MEMORY if (data!=a->data) DXFree(data); #endif return a; } Error _dxfArray_Delete(Array a) { if (a->shape != a->lshape) DXFree((Pointer)(a->shape)); if (a->data != (Pointer)a->ldata) DXFree((Pointer)(a->data)); return OK; } Object _dxfArray_Copy(Array old, enum copy copy) { if (copy==COPY_DATA) DXErrorReturn(ERROR_BAD_PARAMETER, "copying data is not implemented"); return (Object)old; } Array DXAddArrayData(Array a, int start, int n, Pointer data) { CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */ /* expand if necessary */ /* second test guarantees that we allocate a buffer */ if (start+n > a->allocated || a->allocated==0) { /* allocate 25% extra iff this is a realloc */ int alloc = (a->allocated? (start+n)*5/4 : start+n); if (!DXAllocateArray(a, alloc)) return NULL; } /* copy the data */ if (data) memcpy((char *)(a->data)+start*a->size, data, n*a->size); /* record the new number of items */ if (start+n > a->items) a->items = start+n; return a; } Array DXAllocateArray(Array a, int n) { CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */ /* second test guarantees something will be allocated even if 0 length */ if (n > a->allocated || a->allocated==0) { int bytes = n * a->size; Pointer d; if (bytes > sizeof(a->ldata)) { if (a->data == (Pointer)a->ldata) { d = DXAllocate(bytes); if (!d) return NULL; memcpy(d, a->ldata, sizeof(a->ldata)); } else { d = DXReAllocate(a->data, bytes); if (!d) return NULL; } a->data = d; } else a->data = (Pointer)a->ldata; a->allocated = n; } return a; } Array DXTrim(Array a) { #if 0 /* EndField() calls this on all arrays regardless of type */ CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */ #else CHECK(a, CLASS_ARRAY); #endif if (a->allocated > a->items) { if (a->data != (Pointer)a->ldata) { Pointer d = DXReAllocate(a->data, a->items*a->size); if (!d) /* realloc shouldn't fail, but just in case ... */ DXErrorReturn(ERROR_UNEXPECTED, "re-alloc failed!"); a->data = d; } a->allocated = a->items; } return a; } #if 0 /* this might be a useful function to add sometime */ Array DXTrimItems(Array a, int nitems) { CHECKARRAY(a, CLASS_ARRAY); /* only valid for irregular arrays */ /* reset the item count only if smaller, * and release any extra space in either case. */ if (a->items > a->nitems) a->items = a->nitems; return DXTrim(a); } #endif Pointer DXGetArrayData(Array a) { return _dxfGetArrayData(a); } ArrayHandle DXCreateArrayHandle(Array array) { int i; ArrayHandle handle = NULL; Array *terms = NULL; handle = (ArrayHandle)DXAllocateZero(sizeof(struct arrayHandle)); if (! handle) goto error; handle->class = DXGetArrayClass(array); handle->itemSize = DXGetItemSize(array); DXGetArrayInfo(array, &handle->nElements, &handle->type, &handle->cat, NULL, NULL); handle->nValues = handle->itemSize / DXTypeSize(handle->type); if (array->data) { handle->data = array->data; } else if (DXQueryConstantArray(array, NULL, NULL)) { handle->cdata = DXAllocate(handle->itemSize); if (! handle->cdata) goto error; DXQueryConstantArray(array, NULL, handle->cdata); } else switch(handle->class) { case CLASS_REGULARARRAY: handle->origin = DXAllocate(handle->itemSize); handle->delta = DXAllocate(handle->itemSize); if (! handle->origin || ! handle->delta) goto error; DXGetRegularArrayInfo((RegularArray)array, NULL, handle->origin, handle->delta); break; case CLASS_PATHARRAY: break; case CLASS_PRODUCTARRAY: { int i; DXGetProductArrayInfo((ProductArray)array, &handle->nTerms, NULL); terms = (Array *)DXAllocate(handle->nTerms * sizeof(Array)); handle->scr1 = (int *)DXAllocate(handle->itemSize); handle->scr2 = (int *)DXAllocate(handle->itemSize); handle->strides = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); handle->counts = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); handle->scratch = (Pointer *) DXAllocateZero(handle->nTerms * sizeof(Pointer)); handle->handles = (ArrayHandle *) DXAllocateZero(handle->nTerms * sizeof(ArrayHandle)); handle->indices = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); if (! handle->strides || ! handle->counts || ! terms || ! handle->indices || ! handle->scr1 || ! handle->scr2 || ! handle->scratch || ! handle->handles) goto error; DXGetProductArrayInfo((ProductArray)array, NULL, terms); for (i = 0; i < handle->nTerms; i++) { handle->handles[i] = DXCreateArrayHandle(terms[i]); if (NULL == handle->handles[i]) goto error; handle->scratch[i]=DXAllocate(DXGetItemSize(terms[i])); if (NULL == handle->scratch) goto error; DXGetArrayInfo(terms[i], &handle->counts[i], NULL, NULL, NULL, NULL); } DXFree((Pointer)terms); handle->strides[handle->nTerms-1] = 1; for (i = handle->nTerms-2; i >= 0; i--) handle->strides[i] = handle->strides[i+1]*handle->counts[i+1]; } break; case CLASS_MESHARRAY: { int i; DXGetMeshArrayInfo((MeshArray)array, &handle->nTerms, NULL); terms = (Array *)DXAllocate(handle->nTerms * sizeof(Array)); handle->scr1 = (int *)DXAllocate(handle->itemSize); handle->scr2 = (int *)DXAllocate(handle->itemSize); handle->strides = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); handle->counts = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); handle->scratch = (Pointer *) DXAllocateZero(handle->nTerms * sizeof(Pointer)); handle->handles = (ArrayHandle *) DXAllocateZero(handle->nTerms * sizeof(ArrayHandle)); handle->indices = (int *) DXAllocateZero(handle->nTerms * sizeof(int)); if (! handle->strides || ! handle->counts || ! terms || ! handle->scr1 || ! handle->scr2 || ! handle->indices || ! handle->scratch || ! handle->handles) goto error; DXGetMeshArrayInfo((MeshArray)array, NULL, terms); for (i = 0; i < handle->nTerms; i++) { handle->handles[i] = DXCreateArrayHandle(terms[i]); if (NULL == handle->handles[i]) goto error; handle->scratch[i]=DXAllocate(DXGetItemSize(terms[i])); if (NULL == handle->scratch) goto error; DXGetArrayInfo(terms[i], &handle->counts[i], NULL, NULL, NULL, NULL); handle->counts[i] += 1; } DXFree((Pointer)terms); handle->strides[handle->nTerms-1] = 1; for (i = handle->nTerms-2; i >= 0; i--) handle->strides[i] = handle->strides[i+1]*(handle->counts[i+1]-1); } break; default: handle->data = DXGetArrayData(array); break; } return handle; error: DXFreeArrayHandle(handle); DXFree((Pointer)terms); return NULL; } Error DXFreeArrayHandle(ArrayHandle handle) { int i; if (handle) { for (i = 0; i < handle->nTerms; i++) { DXFreeArrayHandle(handle->handles[i]); DXFree(handle->scratch[i]); } DXFree((Pointer)handle->strides); DXFree((Pointer)handle->counts); DXFree((Pointer)handle->handles); DXFree((Pointer)handle->indices); DXFree((Pointer)handle->scratch); DXFree((Pointer)handle->scr1); DXFree((Pointer)handle->scr2); DXFree((Pointer)handle->cdata); DXFree((Pointer)handle->origin); DXFree((Pointer)handle->delta); DXFree((Pointer)handle); } return OK; } #define REGULAR_GETELEMENT(type) \ { \ type *dst = (type *)scratch; \ type *org = (type *)handle->origin; \ type *del = (type *)handle->delta; \ int i; \ for (i = 0; i < handle->nValues; i++) \ *dst++ = *org++ + offset*(*del++); \ } #define MESHARRAY_ADDTERM(type) \ { \ type *dst = (type *)scratch; \ type *right; \ int i, j; \ \ for (i = 1; i < handle->nTerms; i++) \ { \ right = (type *)DXGetArrayEntry(handle->handles[i], \ handle->indices[i], handle->scratch[i]); \ for (j = 0; j < handle->nValues; j++) \ dst[j] += right[j]; \ } \ } static void _dxfTermIndices(ArrayHandle handle, int offset, int *indices) { int i; for (i = 0; i < handle->nTerms-1; i++) { indices[i] = offset / handle->strides[i]; offset = offset % handle->strides[i]; } indices[handle->nTerms-1] = offset; } Pointer DXCalculateArrayEntry(ArrayHandle handle, int offset, Pointer scratch) { if (handle->data) return (Pointer)(((char *)handle->data) + offset*handle->itemSize); else if (handle->cdata) return handle->cdata; else { switch (handle->class) { case CLASS_REGULARARRAY: switch(handle->type) { case TYPE_DOUBLE: REGULAR_GETELEMENT(double); break; case TYPE_FLOAT: REGULAR_GETELEMENT(float); break; case TYPE_INT: REGULAR_GETELEMENT(int); break; case TYPE_UINT: REGULAR_GETELEMENT(uint); break; case TYPE_SHORT: REGULAR_GETELEMENT(short); break; case TYPE_USHORT: REGULAR_GETELEMENT(ushort); break; case TYPE_BYTE: REGULAR_GETELEMENT(byte); break; case TYPE_UBYTE: REGULAR_GETELEMENT(ubyte); break; } break; case CLASS_PATHARRAY: ((int *)scratch)[0] = offset; ((int *)scratch)[1] = offset+1; break; case CLASS_MESHARRAY: { _dxfTermIndices(handle, offset, handle->indices); if (handle->nTerms == 1) { memcpy(scratch, DXGetArrayEntry(handle->handles[0], handle->indices[0], handle->scratch[0]), handle->handles[0]->itemSize); } else { int *left, *right, *dst, *ptr, i, j, k, nItems; memcpy(handle->scr1, DXGetArrayEntry(handle->handles[0], handle->indices[0], handle->scratch[0]), handle->handles[0]->itemSize); nItems = handle->handles[0]->nValues; left = handle->scr1; dst = handle->scr2; for (i = 1; i < handle->nTerms; i++) { if (i == handle->nTerms-1) dst = (int *)scratch; right = (int *)DXGetArrayEntry(handle->handles[i], handle->indices[i], handle->scratch[i]); ptr = dst; for (j = 0; j < nItems; j++) { int tmp = left[j] * handle->counts[i]; for (k = 0; k < handle->handles[i]->nValues; k++) *ptr++ = tmp + right[k]; } nItems *= handle->handles[i]->nValues; ptr = dst; dst = left; left = ptr; } } } break; case CLASS_PRODUCTARRAY: { _dxfTermIndices(handle, offset, handle->indices); if (handle->nTerms == 1) { memcpy(scratch, DXGetArrayEntry(handle->handles[0], handle->indices[0], handle->scratch[0]), handle->handles[0]->itemSize); } else { memcpy(scratch, DXGetArrayEntry(handle->handles[0], handle->indices[0], handle->scratch[0]), handle->handles[0]->itemSize); switch(handle->type) { case TYPE_DOUBLE: MESHARRAY_ADDTERM(double); break; case TYPE_FLOAT: MESHARRAY_ADDTERM(float); break; case TYPE_INT: MESHARRAY_ADDTERM(int); break; case TYPE_UINT: MESHARRAY_ADDTERM(uint); break; case TYPE_SHORT: MESHARRAY_ADDTERM(short); break; case TYPE_USHORT: MESHARRAY_ADDTERM(ushort); break; case TYPE_BYTE: MESHARRAY_ADDTERM(byte); break; case TYPE_UBYTE: MESHARRAY_ADDTERM(ubyte); break; } } } break; } return scratch; } error: return NULL; } /* make string arrays */ Array DXMakeStringList(int n, char *s, ...) { int i, alloc; char **c; va_list arg; Array a; if (n == 0) return NULL; if (n < 0) { DXSetError(ERROR_BAD_PARAMETER, "#10020", "stringlist count"); return NULL; } c = (char **)DXAllocate(n * sizeof(char *)); if (!c) return NULL; c[0] = s; /* collect args */ va_start(arg,s); for (i=1; i maxlen) maxlen = l; } a = DXNewArray(TYPE_STRING, CATEGORY_REAL, 1, maxlen+1); if (!a) return NULL; if (!DXAddArrayData(a, 0, n, NULL)) goto error; p = (char *)DXGetArrayData(a); if (!p) goto error; for (i=0; i