1 /***********************************************************************/ 2 /* Open Visualization Data Explorer */ 3 /* (C) Copyright IBM Corp. 1989,1999 */ 4 /* ALL RIGHTS RESERVED */ 5 /* This code licensed under the */ 6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ 7 /***********************************************************************/ 8 9 /* 10 \section{Array class} 11 12 Dynamic arrays are implemented by re-allocating the storage block 13 pointed to by {\tt data} as necessary, thus increasing the size of the block in 14 proportion to the current size. If only one dynamic array is being 15 created at a time, the overhead is minimal. If two or more are being 16 created simultaneously, the overhead is a small fixed number of copy 17 operations of the entire data. To demonstrate this: Let $\alpha>1$ be the factor by which 18 the block is enlarged. Suppose $N$ is the final size of the block, 19 where $\alpha^n<N<\alpha^{n+1}$. The number of bytes copied in 20 filling the block is $1+\alpha+\alpha^2+\cdots+\alpha^n = 21 (\alpha^{n+1}-1)/(\alpha-1)$. The average number of copy operations is 22 the limit as $n$ goes to infinity of the average over the interval between 23 $\alpha^n$ and $\alpha^{n+1}$ of the ratio between the number of bytes 24 copied and $N$; this can be calculated to be $(\alpha\ln\alpha)/(\alpha-1)^2$. 25 For $\alpha={3\over2}$ we copy the data 2.4 times; for $\alpha={4\over3}$, 26 3.4 times; for $\alpha={5\over4}$, 4.5 times. In any case, if the size of the 27 array is known in advance, it can be pre-allocated. DX also keeps track of 28 a local copy of the data on each processor. 29 */ 30 31 INCLUDE objectClass.X 32 33 SUBCLASS Array OF Object 34 DEFINESC Pointer GetArrayData(Array) 35 IMPLEMENTS Delete GetType GetArrayData Copy 36 37 SUBCLASS SharedArray OF Array 38 IMPLEMENTS Delete GetArrayData 39 40 SUBCLASS RegularArray OF Array 41 IMPLEMENTS Delete GetArrayData 42 43 SUBCLASS PathArray OF Array 44 IMPLEMENTS GetArrayData 45 46 SUBCLASS ProductArray OF Array 47 IMPLEMENTS Delete GetArrayData 48 49 SUBCLASS MeshArray OF Array 50 IMPLEMENTS Delete GetArrayData 51 52 SUBCLASS ConstantArray OF Array 53 IMPLEMENTS GetArrayData 54 55 #define MAX_PROCESSORS 32 /* maximum number of processors */ 56 #define NLSHAPE 5 /* small shape array size */ 57 #define NLDATA 12 /* small data size (in doubles) */ 58 59 struct array { 60 61 struct object object; /* object preamble */ 62 63 Type type; /* char, short, int, float, double */ 64 Category category; /* real, complex, quaternion */ 65 int rank; /* dimensionality */ 66 int *shape; /* extent in each dimension */ 67 int lshape[NLSHAPE]; /* extents for small dims */ 68 69 unsigned int items; /* number of items defined */ 70 int size; /* size of ea item (from type, etc.) */ 71 Pointer data; /* the data itself */ 72 double ldata[NLDATA]; /* room for data (double aligned) */ 73 lock_type inprogress; /* compact data expansion in prog? */ 74 unsigned int allocated; /* number of items allocated */ 75 76 #if 0 77 struct { /* local copies of data: */ 78 int reference; /* number of references */ 79 Pointer data; /* the local data itself */ 80 } local[MAX_PROCESSORS]; /* one for each processor */ 81 #endif 82 }; 83 84 struct sharedarray { /* shared array structure */ 85 struct array array; /* array class preamble */ 86 int id; /* shared memory id */ 87 Pointer base; /* base of shared segment on this proc */ 88 long offset; /* offset of data in segment */ 89 }; 90 91 struct regulararray { /* regular array structure */ 92 struct array array; /* array class preamble */ 93 Pointer origin; /* position of first */ 94 Pointer delta; /* spacing of points */ 95 }; 96 97 struct patharray { /* regular connections structure */ 98 struct array array; /* array class preamble */ 99 int offset; /* information offset relative to */ 100 }; /* field that this is part of */ 101 102 struct productarray { /* product array structure */ 103 struct array array; /* array class preamble */ 104 int nterms; /* number of terms */ 105 Array *terms; /* the terms */ 106 }; 107 108 struct mesharray { /* product array structure */ 109 struct array array; /* array class preamble */ 110 int nterms; /* number of terms */ 111 Array *terms; /* the terms */ 112 }; 113 114 struct constantarray { /* constant array structure */ 115 struct array array; /* array class preamble */ 116 Pointer data; /* constant value */ 117 }; 118 119 Array _dxf_NewArrayV(Type type, Category category, int rank, int *shape, 120 struct array_class *class); 121 122 123 #if 0 /* was if OPTIMIZED */ 124 #define CHECKARRAY(obj, cls) { \ 125 if (!obj) \ 126 return ERROR; \ 127 } 128 #else 129 #define CHECKARRAY(obj, cls) { \ 130 if (!obj) \ 131 return ERROR; \ 132 if (DXGetArrayClass((Array)(obj)) != cls) \ 133 DXErrorReturn(ERROR_BAD_CLASS, "called with array of wrong class"); \ 134 } 135 #endif 136 /** 137 This macro eases the task of checking argument class. Note: This is not needed 138 when a method implementation is called, because {\tt o} and its class will 139 both have been checked by the method. 140 **/ 141 142 /* 143 * These macros are used by GetArrayData for the compact arrays 144 * (RegularArray, ProductArray, PathArray, MeshArray) to lock the 145 * arrays during expansion so that only one processor at a time 146 * does it, avoiding memory leaks. 147 */ 148 149 #define EXPAND_LOCK(a) { \ 150 if (a->array.data) { \ 151 DXsyncmem(); \ 152 return a->array.data; \ 153 } \ 154 DXlock(&a->array.inprogress, DXProcessorId()); \ 155 if (a->array.data) { \ 156 DXunlock(&a->array.inprogress, DXProcessorId());\ 157 DXsyncmem(); \ 158 return a->array.data; \ 159 } \ 160 } 161 162 #define EXPAND_RETURN(a, result) { \ 163 a->array.data = (Pointer)(result); \ 164 DXunlock(&a->array.inprogress, DXProcessorId()); \ 165 return (Pointer)(result); \ 166 } 167 168 #define EXPAND_ERROR(a) { \ 169 DXunlock(&a->array.inprogress, DXProcessorId()); \ 170 return NULL; \ 171 } 172