|
|
1.1 root 1: #include "ideal.h"
2: #include "y.tab.h"
3:
4: void nonlinerr (funcname)
5: char *funcname;
6: {
7: fprintf (stderr, "ideal: %s() of unknown\n >>>Returning 1.0\n", funcname);
8: }
9:
10: static DEPPTR depvarlist = NULL;
11: static boolean incon_warn = TRUE;
12: static boolean nl_warn;
13: boolean nl_fail;
14: static EQNPTR nl_eqns = NULL;
15:
16: INTLPTR expreval (exprn, givennoad)
17: EXPR exprn;
18: NOADPTR givennoad;
19: {
20: /* This routine returns an INTLPTR whose operator
21: is ';'--a promoted commanode containing the
22: dependency list representing the real part in
23: its left field, the imag part in its right */
24: register INTLPTR intl;
25: register EXTLPTR extl;
26: if (!exprn)
27: return (commagen (0.0, 0.0));
28: if (((EXTLPTR)exprn)->leaf) {
29: extl = (EXTLPTR) exprn;
30: dprintf "At a leaf of kind %d\n", extl->kind);
31: switch (extl->kind) {
32: case PATH:
33: return (pathfind (extl->info.path, givennoad));
34: break;
35: case CONST:
36: return (commagen (extl->info.const, 0.0));
37: break;
38: }
39: }
40: intl = (INTLPTR) exprn;
41: if (intl->oper == NAME) {
42: dprintf "Looking for a function named %s\n", idprint ((int) intl->left));
43: } else {
44: dprintf "At an internal node with operator %c\n", intl->oper);
45: }
46: switch (intl->oper) {
47: INTLPTR lefttemp, righttemp, temp, temp2;
48: DEPPTR drek, drek2;
49: float repart, impart, modulus;
50: case NAME:
51: if (((int) intl->left) == lookup ("re")) {
52: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
53: depfree ((DEPPTR) temp->right);
54: temp->right = (EXPR) depgen ((VARPTR) NULL, 0.0);
55: return (temp);
56: } else if (((int) intl->left) == lookup ("im")) {
57: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
58: depfree ((DEPPTR) temp->left);
59: temp->left = temp->right;
60: temp->right = (EXPR) depgen ((VARPTR) NULL, 0.0);
61: return (temp);
62: } else if (((int) intl->left) == lookup ("conj")) {
63: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
64: temp2 = intlgen (
65: ';',
66: (EXPR) depadd (
67: (DEPPTR) NULL, 0.0,
68: (DEPPTR) temp->left, 1.0
69: ),
70: (EXPR) depadd (
71: (DEPPTR) NULL, 0.0,
72: (DEPPTR) temp->right, -1.0
73: )
74: );
75: intlfree (temp);
76: return (temp2);
77: } else if (((int) intl->left) == lookup ("abs")) {
78: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
79: if (!known(temp)) {
80: if (nl_warn)
81: nonlinerr ("abs");
82: nl_fail = !nl_warn;
83: intlfree (temp);
84: return (commagen (1.0, 0.0));
85: } else {
86: repart = Re(temp);
87: impart = Im(temp);
88: intlfree (temp);
89: return (commagen (hypot (repart, impart), 0.0));
90: }
91: } else if (((int) intl->left) == lookup ("cis")) {
92: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
93: if (!known(temp)) {
94: if (nl_warn)
95: nonlinerr ("cis");
96: nl_fail = !nl_warn;
97: intlfree (temp);
98: return (commagen (1.0, 0.0));
99: } else {
100: repart = Re(temp);
101: impart = Im(temp);
102: if (!radflag) {
103: dtor(repart);
104: dtor(impart);
105: }
106: intlfree (temp);
107: if (impart > EPSILON)
108: fprintf (stderr, "ideal: cis of complex value\n >>>Ignoring imaginary part\n");
109: return (commagen (cos (repart), sin (repart)));
110: }
111: } else if (((int) intl->left) == lookup ("int")) {
112: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
113: if (!known(temp)) {
114: if (nl_warn)
115: nonlinerr ("int");
116: nl_fail = !nl_warn;
117: intlfree (temp);
118: return (commagen (1.0,0.0));
119: } else {
120: double intpart;
121: repart = Re(temp);
122: impart = Im(temp);
123: intlfree (temp);
124: if (impart > EPSILON)
125: fprintf (stderr, "ideal: int of complex value\n >>>Ignoring imaginary part\n");
126: modf (repart, &intpart);
127: return (commagen ((float) intpart, 0.0));
128: }
129: } else if (((int) intl->left) == lookup ("atan2")
130: || ((int) intl->left) == lookup ("angle")) {
131: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
132: if (!known(temp)) {
133: if (nl_warn)
134: nonlinerr ("angle");
135: nl_fail = !nl_warn;
136: intlfree (temp);
137: return (commagen (1.0,0.0));
138: } else {
139: repart = Re(temp);
140: impart = Im(temp);
141: intlfree (temp);
142: repart = atan2 (impart, repart);
143: if (!radflag)
144: rtod(repart);
145: return (commagen (repart, 0.0));
146: }
147: } else if (((int) intl->left) == lookup ("E")) {
148: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
149: if (!known(temp)) {
150: if (nl_warn)
151: nonlinerr ("E");
152: nl_fail = !nl_warn;
153: intlfree (temp);
154: return (commagen (1.0, 0.0));
155: } else {
156: repart = Re(temp);
157: impart = Im(temp);
158: if (impart > EPSILON)
159: fprintf (stderr, "ideal: E of complex value\n >>>Ignoring imaginary part\n");
160: repart *= 2*PI;
161: return (commagen (cos (repart), sin (repart)));
162: }
163: } else if (((int) intl->left) == lookup ("unit")) {
164: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
165: if (!known(temp)) {
166: if (nl_warn)
167: nonlinerr ("unit");
168: nl_fail = !nl_warn;
169: intlfree (temp);
170: return (commagen (1.0, 0.0));
171: } else {
172: repart = Re(temp);
173: impart = Im(temp);
174: intlfree (temp);
175: if ((modulus = hypot (repart, impart)) < EPSILON)
176: return (commagen (0.0, 0.0));
177: else return (
178: commagen (
179: repart/modulus,
180: impart/modulus
181: )
182: );
183: }
184: } else if (((int) intl->left) == lookup ("sqrt")) {
185: temp = expreval (((EXPRPTR) intl->right)->expr, givennoad);
186: if (!known(temp)) {
187: if (nl_warn)
188: nonlinerr ("sqrt");
189: nl_fail = !nl_warn;
190: intlfree (temp);
191: return (commagen (1.0, 0.0));
192: } else {
193: repart = Re(temp);
194: impart = Im(temp);
195: intlfree (temp);
196: if ((modulus = hypot (repart, impart)) < EPSILON)
197: return (commagen (0.0, 0.0));
198: else {
199: float theta;
200: modulus = sqrt (modulus);
201: theta = 0.5*atan2 (impart,repart);
202: return (
203: commagen (
204: modulus*cos(theta),
205: modulus*sin(theta)
206: )
207: );
208: };
209: }
210: } else {
211: fprintf (stderr, "ideal: unknown function name: %s\n >>>Returning 1.0\n", idprint ((int) intl->left));
212: return (commagen (1.0, 0.0));
213: }
214: break;
215: case '~':
216: incon_warn = FALSE;
217: /* FALL THROUGH TO '=' case */
218: case '=':
219: {
220: DEPPTR depvarwalk;
221: lefttemp = expreval (intl->left, givennoad);
222: righttemp = expreval (intl->right, givennoad);
223: if (nl_fail) {
224: dprintf "Non-linear equation: failure\n");
225: intlfree (lefttemp);
226: intlfree (righttemp);
227: return (commagen (0.0,0.0));
228: }
229: for (depvarwalk = depvarlist;
230: depvarwalk;
231: depvarwalk = depvarwalk->next) {
232: lefttemp->left = (EXPR) depsubst (
233: (DEPPTR) lefttemp->left,
234: (DEPPTR) depvarwalk->var->deplist,
235: depvarwalk->var
236: );
237: lefttemp->right = (EXPR) depsubst (
238: (DEPPTR) lefttemp->right,
239: (DEPPTR) depvarwalk->var->deplist,
240: depvarwalk->var
241: );
242: righttemp->left = (EXPR) depsubst (
243: (DEPPTR) righttemp->left,
244: (DEPPTR) depvarwalk->var->deplist,
245: depvarwalk->var
246: );
247: righttemp->right = (EXPR) depsubst (
248: (DEPPTR) righttemp->right,
249: (DEPPTR) depvarwalk->var->deplist,
250: depvarwalk->var
251: );
252: }
253: dprintf "equating real parts...\n");
254: drek = depadd (
255: (DEPPTR) lefttemp->left, 1.0,
256: (DEPPTR) righttemp->left, -1.0
257: );
258: eqndo (drek, exprn, givennoad);
259: depfree (drek);
260: if (depvarlist) {
261: /* trick: at most one variable became
262: /* dependent by the above processing,
263: /* so only it must be replaced in the
264: /* equation on the imaginary parts */
265: lefttemp->right = (EXPR) depsubst (
266: (DEPPTR) lefttemp->right,
267: (DEPPTR) depvarlist->var->deplist,
268: depvarlist->var
269: );
270: righttemp->right = (EXPR) depsubst (
271: (DEPPTR) righttemp->right,
272: (DEPPTR) depvarlist->var->deplist,
273: depvarlist->var
274: );
275: }
276: dprintf "equating imag parts...\n");
277: drek = depadd (
278: (DEPPTR) lefttemp->right, 1.0,
279: (DEPPTR) righttemp->right, -1.0
280: );
281: eqndo (drek, exprn, givennoad);
282: depfree (drek);
283: intlfree (lefttemp);
284: return (righttemp);
285: }
286: break;
287: case '+':
288: lefttemp = expreval (intl->left, givennoad);
289: righttemp = expreval (intl->right, givennoad);
290: drek = depadd (
291: (DEPPTR) lefttemp->left, 1.0,
292: (DEPPTR) righttemp->left, 1.0
293: );
294: drek2 = depadd (
295: (DEPPTR) lefttemp->right, 1.0,
296: (DEPPTR) righttemp->right, 1.0
297: );
298: intlfree (lefttemp);
299: intlfree (righttemp);
300: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
301: break;
302: case '-':
303: lefttemp = expreval (intl->left, givennoad);
304: righttemp = expreval (intl->right, givennoad);
305: drek = depadd (
306: (DEPPTR) lefttemp->left, 1.0,
307: (DEPPTR) righttemp->left, -1.0
308: );
309: drek2 = depadd (
310: (DEPPTR) lefttemp->right, 1.0,
311: (DEPPTR) righttemp->right, -1.0
312: );
313: intlfree (lefttemp);
314: intlfree (righttemp);
315: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
316: break;
317: case '*':
318: lefttemp = expreval (intl->left, givennoad);
319: righttemp = expreval (intl->right, givennoad);
320: if (known(lefttemp)) {
321: repart = ((DEPPTR) lefttemp->left)->coeff;
322: impart = ((DEPPTR) lefttemp->right)->coeff;
323: intlfree (lefttemp);
324: drek = depadd (
325: (DEPPTR) righttemp->left, repart,
326: (DEPPTR) righttemp->right, -impart
327: );
328: drek2 = depadd (
329: (DEPPTR) righttemp->left, impart,
330: (DEPPTR) righttemp->right, repart
331: );
332: intlfree (righttemp);
333: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
334: } else if (known(righttemp)) {
335: repart = ((DEPPTR) righttemp->left)->coeff;
336: impart = ((DEPPTR) righttemp->right)->coeff;
337: intlfree (righttemp);
338: drek = depadd (
339: (DEPPTR) lefttemp->left, repart,
340: (DEPPTR) lefttemp->right, -impart
341: );
342: drek2 = depadd (
343: (DEPPTR) lefttemp->left, impart,
344: (DEPPTR) lefttemp->right, repart
345: );
346: intlfree (lefttemp);
347: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
348: } else {
349: if (nl_warn)
350: fprintf (stderr, "ideal: multiplication of two unknowns\n >>>Returning 1.0\n");
351: nl_fail = !nl_warn;
352: intlfree (lefttemp);
353: intlfree (righttemp);
354: return (commagen (1.0, 0.0));
355: }
356: break;
357: case ELEWISE:
358: lefttemp = expreval (intl->left, givennoad);
359: righttemp = expreval (intl->right, givennoad);
360: if (known(lefttemp)) {
361: repart = ((DEPPTR) lefttemp->left)->coeff;
362: impart = ((DEPPTR) lefttemp->right)->coeff;
363: intlfree (lefttemp);
364: drek = depadd (
365: (DEPPTR) righttemp->left, repart,
366: (DEPPTR) NULL, 0.0
367: );
368: drek2 = depadd (
369: (DEPPTR) righttemp->right, impart,
370: (DEPPTR) NULL, 0.0
371: );
372: intlfree (righttemp);
373: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
374: } else if (known(righttemp)) {
375: repart = ((DEPPTR) righttemp->left)->coeff;
376: impart = ((DEPPTR) righttemp->right)->coeff;
377: intlfree (righttemp);
378: drek = depadd (
379: (DEPPTR) lefttemp->left, repart,
380: (DEPPTR) NULL, 0.0
381: );
382: drek2 = depadd (
383: (DEPPTR) lefttemp->right, impart,
384: (DEPPTR) NULL, 0.0
385: );
386: intlfree (lefttemp);
387: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
388: } else {
389: if (nl_warn)
390: fprintf (stderr, "ideal: multiplication of two unknowns\n >>>Returning 1.0\n");
391: nl_fail = !nl_warn;
392: intlfree (lefttemp);
393: intlfree (righttemp);
394: return (commagen (1.0, 0.0));
395: }
396: break;
397: case '/':
398: lefttemp = expreval (intl->left, givennoad);
399: righttemp = expreval (intl->right, givennoad);
400: if (!known(righttemp)) {
401: if (nl_warn)
402: fprintf (stderr, "ideal: division by an unknown\n >>>Returning 1.0\n");
403: nl_fail = !nl_warn;
404: intlfree (lefttemp);
405: intlfree (righttemp);
406: return (commagen (1.0, 0.0));
407: } else {
408: repart = ((DEPPTR) righttemp->left)->coeff;
409: impart = - ((DEPPTR) righttemp->right)->coeff;
410: modulus = repart*repart + impart*impart;
411: intlfree (righttemp);
412: if (modulus < EPSILON*EPSILON) {
413: fprintf (stderr, "ideal: division by zero\n >>>Returning 1.0\n");
414: intlfree (lefttemp);
415: return (commagen (1.0, 0.0));
416: } else {
417: drek = depadd (
418: (DEPPTR) lefttemp->left, repart/modulus,
419: (DEPPTR) lefttemp->right, -impart/modulus
420: );
421: drek2 = depadd (
422: (DEPPTR) lefttemp->left, impart/modulus,
423: (DEPPTR) lefttemp->right, repart/modulus
424: );
425: intlfree (lefttemp);
426: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
427: }
428: }
429: break;
430: case ',':
431: lefttemp = expreval (intl->left, givennoad);
432: righttemp = expreval (intl->right, givennoad);
433: depfree((DEPPTR) lefttemp->right);
434: depfree((DEPPTR) righttemp->right);
435: temp = intlgen (
436: ';',
437: (EXPR) lefttemp->left,
438: (EXPR) righttemp->left
439: );
440: tryfree(lefttemp);
441: tryfree(righttemp);
442: return (temp);
443: break;
444: case ';':
445: drek = depadd (
446: (DEPPTR) intl->left, 1.0,
447: (DEPPTR) NULL, 0.0
448: );
449: drek2 = depadd (
450: (DEPPTR) intl->right, 1.0,
451: (DEPPTR) NULL, 0.0
452: );
453: return (intlgen (';', (EXPR) drek, (EXPR) drek2));
454: case '^':
455: return (expreval (intl->right, givennoad));
456: default:
457: fprintf (stderr, "ideal: unknown operator: %c\n >>>Returning 1.0\n", intl->oper);
458: return (commagen (1.0, 0.0));
459: break;
460: }
461: }
462:
463: void eqndo (deplist, eqn, givennoad)
464: DEPPTR deplist;
465: EXPR eqn;
466: NOADPTR givennoad;
467: {
468: /* when called, equation system says deplist == 0 */
469: if (!deplist->next && !deplist->var) {
470: if (fabs (deplist->coeff) > EPSILON) {
471: if (incon_warn) {
472: fprintf (stderr, "ideal: inconsistent equation in %s named %s\n",
473: idprint (givennoad->defnode->parm->name),
474: idprint (givennoad->defnode->name)
475: );
476: exprprint (((INTLPTR) eqn)->left);
477: fprintf (stderr, "=");
478: exprprint (eqn);
479: fprintf (stderr, "\n");
480: }
481: dprintf "Inconsistent equation\n");
482: } else
483: dprintf "Redundant equation\n");
484: }
485: else {
486: DEPPTR curmax;
487: float maxcoeff;
488: DEPPTR depvarwalk;
489: DEPPTR listwalk;
490: maxcoeff = -1;
491: /* find variable whose coefficient is largest in absolute value */
492: for (listwalk = deplist;
493: listwalk;
494: listwalk = listwalk->next)
495: if (listwalk->var && (maxcoeff < fabs (listwalk->coeff))) {
496: maxcoeff = fabs (listwalk->coeff);
497: curmax = listwalk;
498: }
499: /* get that variable represented in terms of the others */
500: listwalk = depadd (
501: curmax->var->deplist, 1.0,
502: deplist, -1.0/curmax->coeff
503: );
504: depfree (curmax->var->deplist);
505: curmax->var->deplist = listwalk;
506: /* put it on a list of dependent variables
507: /* replace occurrences of it in other dependent variables */
508: if (!depvarlist) {
509: depvarlist = depgen (curmax->var, 0.0);
510: }
511: else {
512: DEPPTR newhead;
513: for (depvarwalk = depvarlist;
514: depvarwalk;
515: depvarwalk = depvarwalk->next) {
516: depvarwalk->var->deplist = depsubst (
517: depvarwalk->var->deplist,
518: curmax->var->deplist,
519: curmax->var
520: );
521: }
522: newhead = depgen (curmax->var, 0.0);
523: newhead->next = depvarlist;
524: depvarlist = newhead;
525: }
526: }
527: }
528:
529: void depvarclean ()
530: {
531: /* clean known variables out of the dependent variable list */
532: DEPPTR prevdep, depvarwalk;
533: DEPNODE nuhead;
534: prevdep = &nuhead;
535: prevdep->next = depvarwalk = depvarlist;
536: while (depvarwalk) {
537: if (!depvarwalk->var->deplist->var) {
538: dprintf "Removing %s(%s) = %f from dependent variable list\n",
539: ISREAL(depvarwalk->var)?"re":"im",
540: idprint (THENAME(depvarwalk->var)),
541: depvarwalk->var->deplist->coeff);
542: prevdep->next = depvarwalk->next;
543: tryfree(depvarwalk);
544: depvarwalk = prevdep->next;
545: } else {
546: prevdep = depvarwalk;
547: depvarwalk = depvarwalk->next;
548: }
549: }
550: depvarlist = nuhead.next;
551: }
552:
553: void reqneval (noadtree)
554: NOADPTR noadtree;
555: {
556: STMTPTR slist[2];
557: STMTPTR eqnwalk;
558: int i;
559: if (!noadtree)
560: return;
561: nl_warn = FALSE;
562: slist[0] = noadtree->defnode->parm->stmtlist;
563: slist[1] = findbox (noadtree->defnode->parm->name,FALSE)->stmtlist;
564: for (i = 0; i < 2; i ++)
565: for (eqnwalk = nextstmt ('=', slist[i]);
566: eqnwalk;
567: eqnwalk = nextstmt ('=', eqnwalk->next)) {
568: INTLPTR junk;
569: nl_fail = FALSE;
570: junk = expreval ((EXPR) eqnwalk->stmt, noadtree);
571: intlfree (junk);
572: if (nl_fail) {
573: EQNPTR nueqn;
574: nueqn = eqngen (
575: (EXPR) eqnwalk->stmt,
576: noadtree
577: );
578: nueqn->next = nl_eqns;
579: nl_eqns = nueqn;
580: nl_fail = FALSE;
581: }
582: depvarclean ();
583: incon_warn = TRUE;
584: }
585: reqneval (noadtree->son);
586: reqneval (noadtree->brother);
587: }
588:
589: void eqneval (noadtree)
590: NOADPTR noadtree;
591: {
592: if (when_bug & 04) bug_on;
593: reqneval (noadtree);
594: bug_off;
595: }
596:
597: void nl_eval ()
598: {
599: static boolean nl_succ;
600: INTLPTR junk;
601: {
602: EQNPTR nl_prev, nl_curr, nl_temp;
603: if (when_bug & 010) bug_on;
604: nl_prev = nl_curr = nl_eqns;
605: nl_temp = NULL;
606: while (nl_curr) {
607: nl_curr = nl_prev->next;
608: nl_prev->next = nl_temp;
609: nl_temp = nl_prev;
610: nl_prev = nl_curr;
611: }
612: nl_eqns = nl_temp;
613: nl_succ = TRUE;
614: }
615: while (nl_eqns && nl_succ) {
616: EQNPTR prev_eqn, nl_walk;
617: EQNNODE dummy_eqn;
618: dprintf "Retrying nonlinear equations\n");
619: prev_eqn = &dummy_eqn;
620: prev_eqn->next = nl_walk = nl_eqns;
621: nl_succ = FALSE;
622: while (nl_walk) {
623: nl_fail = FALSE;
624: junk = expreval (nl_walk->eqn, nl_walk->noad);
625: intlfree (junk);
626: depvarclean ();
627: if (!nl_fail) {
628: prev_eqn->next = nl_walk->next;
629: tryfree(nl_walk);
630: nl_walk = prev_eqn->next;
631: nl_succ = TRUE;
632: } else {
633: prev_eqn = nl_walk;
634: nl_walk = nl_walk->next;
635: }
636: }
637: nl_eqns = dummy_eqn.next;
638: }
639: if (nl_eqns) {
640: EQNPTR nl_walk, nl_next;
641: dprintf "Nonlinear failure\n");
642: nl_warn = TRUE;
643: for (nl_walk = nl_eqns;
644: nl_walk;
645: nl_walk = nl_next) {
646: junk = expreval (nl_walk->eqn, nl_walk->noad);
647: intlfree (junk);
648: depvarclean ();
649: nl_next = nl_walk->next;
650: tryfree(nl_walk);
651: }
652: }
653: bug_off;
654: }
655:
656: void depvarkill ()
657: {
658: /* remove all unknown variables from depvarlist ...
659: no chance for them to be determined now */
660: if (!depvarlist)
661: return;
662: if (when_bug & 020)
663: fprintf (stderr, "killing depvarlist\n");
664: depfree (depvarlist);
665: depvarlist = NULL;
666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.