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 #include <dxconfig.h>
10
11
12
13 #include <stdarg.h>
14 #include <string.h>
15 #include "arrayClass.h"
16
17
18 static MeshArray
_NewMeshArrayV(int n,Array * terms,struct mesharray_class * class)19 _NewMeshArrayV(int n, Array *terms, struct mesharray_class *class)
20 {
21 int i, items, shape;
22 MeshArray a;
23
24 /* figure out and check type */
25 for (i=0, items=1, shape=1; i<n; i++) {
26 Array b = terms[i];
27 if (b->type!=TYPE_INT || b->category!=CATEGORY_REAL || b->rank!=1)
28 DXErrorReturn(ERROR_BAD_TYPE, "Mesh array term has bad type");
29 items *= terms[i]->items;
30 shape *= terms[i]->shape[0];
31 }
32
33 /* create array */
34 a = (MeshArray) _dxf_NewArrayV(TYPE_INT, CATEGORY_REAL, 1, &shape,
35 (struct array_class *)class);
36 if (!a)
37 return NULL;
38
39 /* copy info */
40 a->nterms = n;
41 if (n * sizeof(*terms) <= sizeof(a->array.ldata)) {
42 a->terms = (Array *) a->array.ldata;
43 } else {
44 a->terms = (Array *) DXAllocate(n * sizeof(*terms));
45 if (!a->terms)
46 return NULL;
47 }
48 for (i=0; i<n; i++)
49 a->terms[i] = (Array)DXReference((Object)terms[i]);
50 a->array.items = items;
51
52 return a;
53 }
54
55
56 MeshArray
DXNewMeshArrayV(int n,Array * terms)57 DXNewMeshArrayV(int n, Array *terms)
58 {
59 return _NewMeshArrayV(n, terms, &_dxdmesharray_class);
60 }
61
62
63 MeshArray
DXNewMeshArray(int n,...)64 DXNewMeshArray(int n, ...)
65 {
66 Array terms[100];
67 int i;
68 va_list arg;
69
70 ASSERT(n<100);
71
72 /* collect args */
73 va_start(arg,n);
74 for (i=0; i<n; i++)
75 terms[i] = va_arg(arg, Array);
76 va_end(arg);
77
78 /* call V version */
79 return DXNewMeshArrayV(n, terms);
80 }
81
82
83 MeshArray
DXGetMeshArrayInfo(MeshArray a,int * n,Array * terms)84 DXGetMeshArrayInfo(MeshArray a, int *n, Array *terms)
85 {
86 int i;
87
88 CHECKARRAY(a, CLASS_MESHARRAY);
89
90 if (n)
91 *n = a->nterms;
92
93 if (terms)
94 for (i=0; i<a->nterms; i++)
95 terms[i] = a->terms[i];
96
97 return a;
98 }
99
100
101 Pointer
_dxfMeshArray_GetArrayData(MeshArray a)102 _dxfMeshArray_GetArrayData(MeshArray a)
103 {
104 int i, j, k, l, m, nterms, nle, nre, nlp, nrp, nr;
105 Array *terms;
106 int *result = NULL, *res, *right, *rt, *left, *lt;
107 int freelocal = 0;
108
109 /* DXlock array */
110 EXPAND_LOCK(a);
111
112 nterms = a->nterms;
113 terms = a->terms;
114
115 /* first left operand is first term */
116 left = (int *) DXGetArrayData(terms[0]);
117 nle = terms[0]->items;
118 nlp = terms[0]->shape[0];
119
120 /* copy first term data if nterms is 1 */
121 /* XXX - is there any way to avoid this? */
122 if (nterms==1) {
123
124 int size = nle * nlp * sizeof(int);
125 result = (int *) DXAllocate(size);
126 if (!result)
127 goto error;
128 memcpy(result, left, size);
129
130 /* accumulate product left to right */
131 } else for (i=1; i<nterms; i++) {
132
133 /* right operand is next term */
134 right = (int *) DXGetArrayDataLocal(terms[i]);
135 if (!right) {
136 freelocal = 0;
137 right = (int *) DXGetArrayData(terms[i]);
138 if (!right)
139 goto error;
140 } else
141 freelocal = 1;
142
143 nre = terms[i]->items;
144 nrp = terms[i]->shape[0];
145
146 /* calculate nr, the number of points in right operand */
147 for (j=0, nr= -1; j<nre*nrp; j++)
148 if (right[j] > nr)
149 nr = right[j];
150 nr += 1;
151
152 /* allocate result */
153 res = result = (int *) DXAllocate(nle*nre*nlp*nrp*sizeof(int));
154 if (!result)
155 goto error;
156
157 /* left operand times right operand */
158 switch (nrp) {
159 case 2:
160 for (j=0, lt=left; j<nle; j++, lt+=nlp) /* ea left elt */
161 for (k=0, rt=right; k<nre; k++, rt+=nrp)/* ea right elt */
162 for (l=0; l<nlp; l++) { /* ea left point */
163 int tmp = lt[l]*nr; /* help the compiler */
164 *res++ = tmp + rt[0]; /* new point number */
165 *res++ = tmp + rt[1]; /* new point number */
166 }
167 break;
168
169 default:
170 for (j=0, lt=left; j<nle; j++, lt+=nlp) /* ea left elt */
171 for (k=0, rt=right; k<nre; k++, rt+=nrp)/* ea right elt */
172 for (l=0; l<nlp; l++) { /* ea left point */
173 int tmp = lt[l]*nr; /* help the compiler */
174 for (m=0; m<nrp; m++) /* ea right point */
175 *res++ = tmp + rt[m]; /* new point number */
176 }
177 break;
178 }
179
180 /* next left operand is result */
181 if (i>1)
182 DXFree((Pointer)left);
183 left = result;
184 nle *= nre;
185 nlp *= nrp;
186
187 if (freelocal)
188 DXFreeArrayDataLocal(terms[i], (Pointer)right);
189 }
190
191 ASSERT(nle==a->array.items);
192 ASSERT(nlp==a->array.shape[0]);
193
194 /* DXunlock and return */
195 EXPAND_RETURN(a, result);
196
197 error:
198 if (freelocal)
199 DXFreeArrayDataLocal(terms[i], (Pointer)right); /* and fall thru */
200 EXPAND_ERROR(a);
201 }
202
203 Error
_dxfMeshArray_Delete(MeshArray a)204 _dxfMeshArray_Delete(MeshArray a)
205 {
206 int i;
207 for (i=0; i<a->nterms; i++)
208 DXDelete((Object)a->terms[i]);
209 if ((Pointer)a->terms != (Pointer)a->array.ldata)
210 DXFree((Pointer)a->terms);
211 return _dxfArray_Delete((Array)a);
212 }
213
214 MeshArray
DXSetMeshOffsets(MeshArray a,int * offsets)215 DXSetMeshOffsets(MeshArray a, int *offsets)
216 {
217 int i, n;
218 Array terms[100];
219 if (!DXGetMeshArrayInfo(a, &n, terms))
220 return NULL;
221 ASSERT(n<100);
222 for (i=0; i<n; i++)
223 if (DXGetArrayClass(terms[i])==CLASS_PATHARRAY)
224 if (!DXSetPathOffset((PathArray)terms[i], offsets[i]))
225 return NULL;
226 return a;
227 }
228
229 MeshArray
DXGetMeshOffsets(MeshArray a,int * offsets)230 DXGetMeshOffsets(MeshArray a, int *offsets)
231 {
232 int i, n;
233 Array terms[100];
234 if (!DXGetMeshArrayInfo(a, &n, terms))
235 return NULL;
236 ASSERT(n<100);
237 for (i=0; i<n; i++)
238 if (!DXGetPathOffset((PathArray)terms[i], offsets+i))
239 return NULL;
240 return a;
241 }
242