/[ascend]/trunk/base/generic/compiler/dimen.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/dimen.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 640 - (show annotations) (download) (as text)
Mon May 29 06:35:14 2006 UTC (14 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 12108 byte(s)
Fixing bug #267 in trunk.
1 /*
2 * Dimension implementation routines
3 * by Tom Epperly
4 * Part of Ascend
5 * Version: $Revision: 1.9 $
6 * Version control file: $RCSfile: dimen.c,v $
7 * Date last modified: $Date: 1997/10/28 19:20:32 $
8 * Last modified by: $Author: mthomas $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
13 *
14 * The Ascend Language Interpreter is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * The Ascend Language Interpreter is distributed in hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with the program; if not, write to the Free Software Foundation,
26 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
27 * COPYING.
28 *
29 */
30
31 #include <utilities/ascConfig.h>
32 #include "compiler.h"
33 #include <utilities/ascPanic.h>
34 #include <utilities/ascMalloc.h>
35 #include <utilities/error.h>
36 #include <general/list.h>
37 #include "fractions.h"
38 #include "dimen.h"
39 #include <general/mathmacros.h>
40
41 struct gl_list_t *g_dimen_list;
42 dim_type *g_wild_dimen,*g_trig_dimen,*g_dimensionless;
43 #ifndef lint
44 static CONST char DimenID[] = "$Id: dimen.c,v 1.9 1997/10/28 19:20:32 mthomas Exp $";
45 #endif
46
47 #define WILD(d) ((d)->wild & DIM_WILD)
48 /* test a DIMENSION pointer for being wild or not */
49
50 char *DimNames[NUM_DIMENS]={
51 /* keep this structure current with defines in dimen.h */
52 "M",
53 "Q",
54 "L",
55 "T",
56 "TMP",
57 "C",
58 "E",
59 "LUM",
60 "P",
61 "S"
62 };
63
64
65 void InitDimenList(void)
66 {
67 /* FPRINTF(ASCERR,"INITIALISING DIMENSION LIST\n"); */
68
69 g_dimen_list = gl_create(200L);
70 AssertMemory(g_dimen_list);
71 g_wild_dimen = (dim_type *)ascmalloc((unsigned)sizeof(dim_type));
72 AssertAllocatedMemory(g_wild_dimen,sizeof(dim_type));
73 g_trig_dimen = (dim_type *)ascmalloc((unsigned)sizeof(dim_type));
74 AssertAllocatedMemory(g_trig_dimen,sizeof(dim_type));
75 g_dimensionless = (dim_type *)ascmalloc((unsigned)sizeof(dim_type));
76 AssertAllocatedMemory(g_dimensionless,sizeof(dim_type));
77 assert((g_wild_dimen!=NULL)&&(g_dimensionless!=NULL)&&(g_trig_dimen!=NULL));
78 ClearDimensions(g_wild_dimen);
79 ClearDimensions(g_trig_dimen);
80 ClearDimensions(g_dimensionless);
81 g_dimensionless->wild=0;
82 g_wild_dimen->wild = DIM_WILD;
83 g_trig_dimen->wild = 0;
84 SetDimFraction(*g_trig_dimen,D_PLANE_ANGLE,
85 CreateFraction((FRACPART)1,(FRACPART)1));
86 gl_insert_sorted(g_dimen_list,g_dimensionless,(CmpFunc)CmpDimen);
87 gl_insert_sorted(g_dimen_list,g_wild_dimen,(CmpFunc)CmpDimen);
88 gl_insert_sorted(g_dimen_list,g_trig_dimen,(CmpFunc)CmpDimen);
89 }
90
91 void DestroyDimenList(void)
92 {
93 gl_free_and_destroy(g_dimen_list);
94 g_wild_dimen = g_dimensionless = NULL;
95 }
96
97 int IsWild(CONST dim_type *d)
98 {
99 if (d != NULL) {
100 return (WILD(d));
101 } else {
102 FPRINTF(ASCERR,"IsWild called on NULL dimension pointer\n");
103 return 1;
104 }
105 }
106
107 int OddDimension(CONST dim_type *dimp)
108 {
109 int i;
110 if (!dimp || IsWild(dimp)) return 1;
111 for (i=0;i<NUM_DIMENS;i++)
112 if (Denominator(GetDimFraction(*dimp,i))!=1 ||
113 (Numerator(GetDimFraction(*dimp,i))%2) )
114 return 1;
115 return 0;
116 }
117
118 /* return 1 if fractional, null or wild, 0 otherwise */
119 static int FractionalDimension(CONST dim_type *dimp)
120 {
121 int i;
122 if (!dimp || IsWild(dimp)) return 1;
123 for (i=0;i<NUM_DIMENS;i++)
124 if (Denominator(GetDimFraction(*dimp,i))!=1) return 1;
125 return 0;
126 }
127
128 int NonCubicDimension(CONST dim_type *dimp)
129 {
130 int i;
131 if (!dimp || IsWild(dimp)) return 1;
132 for (i=0;i<NUM_DIMENS;i++)
133 if (Denominator(GetDimFraction(*dimp,i))!=1 ||
134 (Numerator(GetDimFraction(*dimp,i))%3) )
135 return 1;
136 return 0;
137 }
138
139 void CopyDimensions(CONST dim_type *src, dim_type *dest)
140 {
141 *dest = *src;
142 }
143
144 CONST dim_type *SquareDimension(CONST dim_type *dim, int check)
145 {
146 if (!dim) return NULL;
147 if (IsWild(dim)) return WildDimension();
148 if (check && FractionalDimension(dim)) return NULL;
149 else {
150 dim_type d;
151 struct fraction sqr=CreateFraction((FRACPART)2,(FRACPART)1);
152 d=ScaleDimensions(dim,sqr);
153 return (FindOrAddDimen(&d));
154 }
155 }
156
157 CONST dim_type *HalfDimension(CONST dim_type *dim, int check)
158 {
159 if (!dim) return NULL;
160 if (IsWild(dim)) return WildDimension();
161 if (check && OddDimension(dim)) return NULL;
162 else {
163 dim_type d;
164 struct fraction half=CreateFraction((FRACPART)1,(FRACPART)2);
165 d=ScaleDimensions(dim,half);
166 return (FindOrAddDimen(&d));
167 }
168 }
169
170 CONST dim_type *CubeDimension(CONST dim_type *dim, int check)
171 {
172 if (!dim) return NULL;
173 if (IsWild(dim)) return WildDimension();
174 if (check && FractionalDimension(dim)) return NULL;
175 else {
176 dim_type d;
177 struct fraction cub=CreateFraction((FRACPART)3,(FRACPART)1);
178 d=ScaleDimensions(dim,cub);
179 return (FindOrAddDimen(&d));
180 }
181 }
182
183 static FRACPART topmax(CONST dim_type *dim) {
184 int i;
185 FRACPART biggest = 0;
186 for (i=0;i<NUM_DIMENS;i++) {
187 biggest = MAX(ABS(Numerator(GetDimFraction(*dim,i))),biggest);
188 }
189 return biggest;
190 }
191
192 CONST dim_type *PowDimension(long mult, CONST dim_type *dim, int check)
193 {
194 if (!dim) return NULL;
195 if (IsWild(dim)) return dim;
196 if (dim==Dimensionless()) return dim;
197 if (check && FractionalDimension(dim)) return NULL;
198 if ((long)FRACMAX < mult*topmax(dim)) return NULL;
199 else {
200 dim_type d;
201 struct fraction new;
202 new = CreateFraction((FRACPART)mult,(FRACPART)1);
203 d = ScaleDimensions(dim,new);
204 return (FindOrAddDimen(&d));
205 }
206 }
207
208 CONST dim_type *ThirdDimension(CONST dim_type *dim, int check)
209 {
210 if (!dim) return NULL;
211 if (IsWild(dim)) return WildDimension();
212 if (check && NonCubicDimension(dim)) return NULL;
213 else {
214 dim_type d;
215 struct fraction third=CreateFraction((FRACPART)1,(FRACPART)3);
216 d=ScaleDimensions(dim,third);
217 return (FindOrAddDimen(&d));
218 }
219 }
220
221 void SetWild(dim_type *dim)
222 {
223 assert(dim!=NULL);
224 dim->wild=DIM_WILD;
225 }
226
227 int SameDimen(CONST dim_type *d1, CONST dim_type *d2)
228 {
229 assert(d1!=NULL);
230 assert(d2!=NULL);
231
232 if (d1==d2 || (WILD(d1) && WILD(d2)) ) return 1;
233 /* same pointer or both wild return now */
234
235 if ( WILD(d1) || WILD(d2) ) return 0;
236 /* one is wild, other not, so punt */
237
238 return ( memcmp((char *)d1->f,(char *)d2->f,
239 (sizeof(struct fraction)*NUM_DIMENS)) ==0 );
240 }
241
242 int CmpDimen(CONST dim_type *d1, CONST dim_type *d2)
243 {
244 register unsigned c;
245 register int i;
246 assert(d1!=NULL);
247 assert(d2!=NULL);
248 if (WILD(d1)) {
249 if (WILD(d2)) {
250 return 0;
251 } else {
252 return -1;
253 }
254 }
255 if (WILD(d2)) { return 1; }
256 for(c=0;c<NUM_DIMENS;c++) {
257 i = CmpF( GetDimFraction(*d1,c), GetDimFraction(*d2,c) );
258 if (i<0) {
259 return -1;
260 } else {
261 if (i>0) {
262 return 1;
263 }
264 /* else continue to next dimen */
265 }
266 }
267 return 0;
268 }
269
270 void ClearDimensions(dim_type *d)
271 {
272 register unsigned c;
273 struct fraction f;
274 assert(d!=NULL);
275 f = CreateFraction((FRACPART)0,(FRACPART)1);
276 d->wild = 0;
277 for(c=0;c<NUM_DIMENS;c++)
278 SetDimFraction(*d,c,f);
279 }
280
281 CONST dim_type *Dimensionless(void)
282 {
283 AssertAllocatedMemory(g_dimensionless,sizeof(dim_type));
284 return g_dimensionless;
285 }
286
287 CONST dim_type *TrigDimension(void)
288 {
289 AssertAllocatedMemory(g_trig_dimen,sizeof(dim_type));
290 return g_trig_dimen;
291 }
292
293 CONST dim_type *WildDimension(void)
294 {
295 AssertAllocatedMemory(g_wild_dimen,sizeof(dim_type));
296 return g_wild_dimen;
297 }
298
299 static
300 dim_type *CopyDimen(register CONST dim_type *d)
301 {
302 register dim_type *result;
303 assert(d!=NULL);
304 result = (dim_type *)ascmalloc((unsigned)sizeof(dim_type));
305 ascbcopy((char *)d,(char *)result,sizeof(dim_type));
306 AssertAllocatedMemory(result,sizeof(dim_type));
307 return result;
308 }
309
310 CONST dim_type *FindOrAddDimen(CONST dim_type *d)
311 {
312 register unsigned long place;
313 register dim_type *result;
314 if ((place=gl_search(g_dimen_list,d,(CmpFunc)CmpDimen))!=0){
315 result = gl_fetch(g_dimen_list,place);
316 }
317 else {
318 result = CopyDimen(d);
319 gl_insert_sorted(g_dimen_list,result,(CmpFunc)CmpDimen);
320 }
321 AssertAllocatedMemory(result,sizeof(dim_type));
322 return result;
323 }
324
325 dim_type AddDimensions(CONST dim_type *d1, CONST dim_type *d2)
326 {
327 register unsigned c;
328 dim_type result;
329 ClearDimensions(&result);
330 if (WILD(d1)||WILD(d2)) {
331 result.wild = DIM_WILD;
332 } else {
333 for(c=0;c<NUM_DIMENS;c++) {
334 SetDimFraction(result,c,
335 AddF(GetDimFraction(*d1,c),GetDimFraction(*d2,c)));
336 }
337 }
338 return result;
339 }
340
341 CONST dim_type *SumDimensions(CONST dim_type *d1, CONST dim_type *d2,int check)
342 {
343 register unsigned c;
344 dim_type result;
345 if (check && (FractionalDimension(d1) || FractionalDimension(d2)) ) {
346 return NULL;
347 }
348 ClearDimensions(&result);
349 if (WILD(d1)||WILD(d2)) {
350 return WildDimension();
351 } else {
352 for(c=0;c<NUM_DIMENS;c++) {
353 SetDimFraction(result,c,
354 AddF(GetDimFraction(*d1,c),GetDimFraction(*d2,c)));
355 }
356 }
357 return (FindOrAddDimen(&result));
358 }
359
360 dim_type SubDimensions(CONST dim_type *d1, CONST dim_type *d2)
361 {
362 register unsigned c;
363 dim_type result;
364 ClearDimensions(&result);
365 if (WILD(d1)||WILD(d2)) {
366 result.wild = DIM_WILD;
367 } else {
368 for(c=0;c<NUM_DIMENS;c++) {
369 SetDimFraction(result,c,
370 SubF(GetDimFraction(*d1,c),GetDimFraction(*d2,c)));
371 }
372 }
373 return result;
374 }
375
376 CONST dim_type *DiffDimensions(CONST dim_type *d1,
377 CONST dim_type *d2,
378 int check)
379 {
380 register unsigned c;
381 dim_type result;
382 if (check && (FractionalDimension(d1) || FractionalDimension(d2)) ){
383 return NULL;
384 }
385 ClearDimensions(&result);
386 if (WILD(d1)||WILD(d2)) {
387 return WildDimension();
388 } else {
389 for(c=0;c<NUM_DIMENS;c++) {
390 SetDimFraction(result,c,
391 SubF(GetDimFraction(*d1,c),GetDimFraction(*d2,c)));
392 }
393 }
394 return (FindOrAddDimen(&result));
395 }
396
397 dim_type ScaleDimensions(CONST dim_type *dim, struct fraction frac)
398 {
399 dim_type result;
400 register unsigned c;
401 result = *dim;
402 if (result.wild & DIM_WILD) return result;
403 for(c=0;c<NUM_DIMENS;c++) {
404 SetDimFraction(result,c,MultF(frac,GetDimFraction(*dim,c)));
405 }
406 return result;
407 }
408
409 void PrintDimen(FILE *file, CONST dim_type *dim)
410 {
411 int printed;
412 if (WILD(dim)) {
413 FPRINTF(file,"wild");
414 } else {
415 int i;
416 printed = 0;
417 for (i=0;i<NUM_DIMENS; i++) {
418 if (Numerator(dim->f[i])) {
419 FPRINTF(file,"%d/%d%s ",Numerator(dim->f[i]),Denominator(dim->f[i]),
420 DimName(i));
421 printed = 1;
422 }
423 }
424 if (printed == 0) FPRINTF(file,"dimensionless");
425 }
426 }
427
428 ASC_DLLSPEC(void) PrintDimenMessage(CONST char *message
429 , CONST char *label1, CONST dim_type *d1
430 , CONST char *label2, CONST dim_type *d2
431 ){
432 /*
433 error_reporter_start(ASC_USER_ERROR,NULL,0,NULL);
434 FPRINTF(ASCERR,"%s: %s='", message, label1);
435 PrintDimen(ASCERR,d1);
436 FPRINTF(ASCERR,"', %s='",label2);
437 PrintDimen(ASCERR,d2);
438 FPRINTF(ASCERR,"'");
439 error_reporter_end_flush();
440 */
441 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Invalid dimensions");
442 }
443
444
445 void DumpDimens(FILE *file)
446 {
447 register unsigned long c,len;
448 len = gl_length(g_dimen_list);
449 FPRINTF(file,"Dimensions dump\n");
450 for(c=1;c<=len;c++) {
451 PrintDimen(file,(dim_type *)gl_fetch(g_dimen_list,c));
452 PUTC('\n',file);
453 }
454 }
455
456 CONST dim_type *CheckDimensionsMatch(CONST dim_type *d1, CONST dim_type *d2)
457 {
458 if (WILD(d1)) return d2;
459 if (WILD(d2)||d1 == d2) return d1;
460 if (CmpDimen(d1,d2)==0) return d1;
461 return NULL;
462 }
463
464 void ParseDim(dim_type *dim, CONST char *c)
465 {
466 int i;
467 assert((dim!=NULL)&&(c!=NULL));
468 ClearDimensions(dim);
469 for( i=0; i<NUM_DIMENS && strcmp(c,DimNames[i]); i++ ) ;
470 if( i>=NUM_DIMENS ) FPRINTF(ASCERR,"Dimension %s unknown.\n",c);
471 else SetDimFraction(*dim,i,CreateFraction((FRACPART)1,(FRACPART)1));
472 }
473
474 char *DimName(CONST int ndx)
475 {
476 if( ndx >= 0 && ndx < NUM_DIMENS )
477 return( DimNames[ndx] );
478 else
479 return NULL;
480 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22