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