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