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