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 #include "../base/defines.h"
11
12
13 #include "DXTensor.h"
14 #include "DXValue.h"
15 #include "DXStrings.h"
16 #include "lex.h"
17
18 //
19 // This does not need to be a member function.
20 // It checks to see if the string in s represents a valid Tensor.
21 // index is set to point to the character following the lexed tensor.
22 //
23 boolean
IsTensor(const char * s,int & index)24 IsTensor(const char *s, int& index )
25 {
26 DXTensor t;
27
28 return (t.setValue(s,index));
29 }
30
31 //
32 // This does not need to be a member function.
33 // It checks to see if the string in s represents a valid vector.
34 // index is set to point to the character following the lexed vector.
35 //
36 boolean
IsVector(const char * s,int & index,int & tuple)37 IsVector(const char *s, int& index, int& tuple)
38 {
39 DXTensor t;
40 int tindex = index;
41
42 if (t.setValue(s, tindex) && (t.getDimensions() == 1)) {
43 tuple = t.getDimensionSize(1);
44 index = tindex;
45 return TRUE;
46 }
47
48 return FALSE;
49 }
50
51
52
~DXTensor()53 DXTensor::~DXTensor()
54 {
55 int i;
56
57 if (this->dimensions > 1) {
58 int components=this->dim_sizes[0];
59 for (i=0 ; i<components; i++)
60 if (this->tensors[i])
61 delete this->tensors[i];
62 if (this->tensors) delete this->tensors;
63 } else {
64 if (this->scalars) delete this->scalars;
65 }
66 if (this->strval)
67 delete this->strval;
68 if (this->dim_sizes)
69 delete this->dim_sizes;
70 }
71
72 DXTensor*
dup()73 DXTensor::dup()
74 {
75 int i, components;
76 DXTensor *t;
77
78 t = new DXTensor;
79 t->dimensions = dimensions;
80 t->dim_sizes = new char[dimensions];
81 ASSERT(t->dim_sizes);
82 for (i=0 ; i<dimensions ; i++)
83 t->dim_sizes[i] = dim_sizes[i];
84 components=dim_sizes[0];
85
86 if (dimensions > 1) {
87 t->tensors = new DXTensor*[components];
88 for (i=0 ; i<components; i++)
89 t->tensors[i] = tensors[i]->dup();
90 } else {
91 t->scalars = new double[components];
92 ASSERT(t->scalars);
93 for (i=0 ; i<components; i++)
94 t->scalars[i] = scalars[i];
95 }
96 return t;
97 }
98
99
100 #if 0 // 8/18/93
101 #include <memory.h>
102 static void *
103 Realloc (void *ptr, int size)
104 {
105 char *nptr = new char[size];
106 if (ptr)
107 {
108 memcpy((char*)nptr, ptr, size);
109 delete ptr;
110 }
111 return nptr;
112 }
113 #endif
114
115 //
116 // Set the value of this according to the value parsed from s.
117 // Return TRUE on success, FALSE on failure.
118 // On successful return, index points to the character following the
119 // the last character in the successfully parsed value found in s.
120 // On failure, index is unchanged.
121 //
122 boolean
setValue(const char * s,int & index)123 DXTensor::setValue(const char *s, int& index)
124 {
125 int j;
126 int components = 0;
127 int ndim = 1, loc_index = index;
128 char c;
129 boolean saw_value = FALSE, saw_right_bracket = FALSE;
130 boolean saw_scalar = FALSE;
131 DXTensor *subv = NUL(DXTensor*);
132
133 SkipWhiteSpace(s,loc_index);
134
135 if (s[loc_index] != '[')
136 return FALSE;
137 loc_index++;
138
139 while (s[loc_index]) {
140 SkipWhiteSpace(s,loc_index);
141 c = s[loc_index];
142 if (c == '[') {
143 /* Vectors are not allowed if we already saw a scalar */
144 if (saw_scalar)
145 goto error;
146 subv = new DXTensor;
147 if (!subv->setValue(s, loc_index)) {
148 delete subv;
149 goto error;
150 }
151 this->tensors = (DXTensor**)REALLOC(this->tensors,
152 ++components*sizeof(DXTensor*));
153 ASSERT(this->tensors);
154
155 this->tensors[components-1] = subv;
156 if (ndim == 1) { /* First sub-component */
157 /* Copy the sub-dimensions up to this vector */
158 ndim += subv->dimensions;
159 this->dim_sizes = (char*)REALLOC(this->dim_sizes,
160 ndim * sizeof(*dim_sizes));
161 ASSERT(this->dim_sizes);
162 for (j=0 ; j<subv->dimensions ; j++ )
163 this->dim_sizes[j+1] = subv->dim_sizes[j];
164 } else {
165 /* Ensure that next elements have the correct dimensionality */
166 if (subv->dimensions != ndim-1) {
167 delete subv;
168 goto error;
169 }
170 for (j=1 ; j<ndim ; j++)
171 if (this->dim_sizes[j] != subv->dim_sizes[j-1]) {
172 this->tensors[components-1] = NULL;
173 delete subv;
174 goto error;
175 }
176 }
177 saw_value = TRUE;
178 } else if (c == ']') {
179 if (saw_value == FALSE)
180 goto error;
181 saw_scalar = FALSE;
182 saw_right_bracket = TRUE;
183 loc_index++;
184 break;
185 } else if (c == ',') {
186 if (!saw_value) /* This checks for ',,' */
187 goto error;
188 saw_value = FALSE;
189 saw_scalar = FALSE;
190 loc_index++;
191 } else {
192 /* Scalars are not allowed if we already saw a sub-vector */
193 double val;
194 int matches, tmp = loc_index;
195 if (ndim != 1) goto error;
196 if (!IsScalar(s,tmp))
197 goto error;
198
199 matches = sscanf(&s[loc_index],"%lg", &val);
200 if ((matches == 0) || (matches == EOF))
201 goto error;
202 loc_index = tmp;
203
204 this->scalars =(double*)REALLOC(this->scalars,
205 ++components * sizeof(*scalars));
206 ASSERT(this->scalars);
207 this->scalars[components-1] = val;
208 saw_value = TRUE;
209 saw_scalar = TRUE;
210 }
211 }
212
213 if ((components == 0) || !saw_right_bracket)
214 goto error;
215
216 /* Set the dimension at this level of brackets */
217 if (!this->dim_sizes)
218 this->dim_sizes = new char;
219 this->dim_sizes[0] = components;
220 this->dimensions = ndim;
221
222 // Be sure that the string representation is cleared when the value changes.
223 if (strval) {
224 delete strval;
225 this->strval = NUL(char*);
226 }
227
228 index = loc_index;
229 return TRUE;
230
231 error:
232 return FALSE;
233
234 }
235
236 void
printValue()237 DXTensor::printValue()
238 {
239 int i;
240
241 printf("Dimensions (%d) Dim Sizes (", this->dimensions);
242 for (i=0 ; i<this->dimensions ; i++)
243 printf("%d ",this->dim_sizes[i]);
244
245 printf(")\n Value : '%s'\n",this->getValueString());
246
247 }
248
249 //
250 // Parse a string that represents an (N x M x...)-dimensional Tensor and set
251 // the value represented into this->scalars[].
252 // Return TRUE on success, FALSE otherwise.
253 //
254 //
255 boolean
setValue(const char * s)256 DXTensor::setValue(const char *s)
257 {
258 int i;
259
260 i = 0;
261 return this->setValue(s, i);
262 }
263
264 //
265 // On entrance, index points to the location to begin insterting characters
266 // into s.
267 // On exit, index points to the NULL in the string.
268 //
269 char *
formatTensor(char * s,int & index)270 DXTensor::formatTensor(char *s, int& index)
271 {
272 int i,components = dim_sizes[0];
273
274 s[index++] = '[';
275 s[index++] = ' ';
276 s[index] = '\0';
277
278 if (dimensions > 1) {
279 for (i=0 ; i<components; i++) {
280 tensors[i]->formatTensor(s,index);
281 if (i != (components-1))
282 s[index++] = ' ';
283 s[index] = '\0';
284 }
285 } else {
286 for (i=0 ; i<components; i++) {
287 char buf[128];
288 DXValue::FormatDouble(scalars[i], buf);
289 int cnt = strlen(buf);
290 strcpy(&s[index],buf);
291 index += cnt;
292 if (i != (components-1)) s[index++] = ' ';
293 s[index] = '\0';
294 }
295 }
296
297 s[index++] = ' ';
298 s[index++] = ']';
299 s[index] = '\0';
300
301 return s;
302 }
303
304 //
305 // Return the a pointer to a string value of a Tensor.
306 // If you intend to use the string after the Tensor is destroyed or its value
307 // has changed you should make a copy of the string passed back.
308 //
309 const char *
getValueString()310 DXTensor::getValueString()
311 {
312 int i, cnt;
313
314 if (strval)
315 return (strval);
316
317 #if 0
318 values = 1;
319 for (i=0 ; i<dimensions ; i++)
320 values *= dim_sizes[i];
321 brackets = 1;
322 for (i=0 ; i<dimensions-1 ; i++)
323 brackets += 2 * dim_sizes[i] * brackets;
324 brackets += 2; // For 2 outer brackets
325 cnt = 9 * values + brackets + (brackets + values);
326 #else
327 cnt = 128; // FIXME
328 #endif
329
330 strval = new char[cnt];
331
332 i = 0;
333 formatTensor(strval,i);
334
335 // Let's be sure we didn't overrun the array.
336 ASSERT(i < cnt);
337
338 return (strval);
339
340 }
setVectorComponentValue(int component,double val)341 boolean DXTensor::setVectorComponentValue(int component, double val)
342 {
343 ASSERT(this->getDimensions() == 1);
344 ASSERT(this->dim_sizes[0] >= component);
345 this->scalars[component-1] = val;
346 if (this->strval) {
347 delete this->strval;
348 this->strval = NULL;
349 }
350 return TRUE;
351 }
352
353 //
354 // Get the number of items in the given dimension.
355 // Dimensions are indexed from 1.
356 //
getDimensionSize(int dim)357 int DXTensor::getDimensionSize(int dim)
358 {
359 ASSERT(dim > 0);
360 ASSERT(this->getDimensions() >= dim);
361 ASSERT(this->dim_sizes);
362
363 return this->dim_sizes[dim-1];
364 }
365