home *** CD-ROM | disk | FTP | other *** search
- /*
- * icalc - complex-expression parser
- *
- * Special functions for icalc, such as sum, prod etc.
- *
- * (C) Martin W Scott, 1991.
- */
-
- #include <stdio.h>
- #include "complex.h"
- #include "constant.h"
- #include "complex.tab.h"
-
- extern int silent;
-
- #define SUMMATION 1
- #define PRODUCT 2
- #define LOOP 3
- #define VLOOP 4 /* (verbose loop) */
-
- /*
- * General iteration function.
- *
- * Used for sums, products and general iteration.
- *
- */
- static Complex iterate(al,how)
- ArgList *al; /* argument list */
- int how; /* sum, product or loop */
- {
- Node *expr; /* expression to iterate */
- Symbol *index; /* index to iterate over */
- double *idxval, to; /* real part of index, what to iterate upto */
- char *mode; /* mode as string, for error message */
- Complex cplx; /* general purpose complex variable */
-
-
- if (al) /* agruments were passed */
- {
- expr = al->node; /* get expression to iterate */
-
- if (al = al->next) /* get upper limit */
- {
- cplx = cinteger(eval_tree(al->node));
- to = cplx.real;
-
- if ((al = al->next) && !al->next) /* get index... */
- { /* no more args? */
- (void)eval_tree(al->node);
- if (al->node->type == '=' || al->node->type == VAR)
- {
- index = al->node->contents.sym;
-
- if (index->type != VAR) /* undefined */
- index->type = VAR;
-
- switch (how) /* initial */
- {
- case SUMMATION:
- cplx = zero; break;
- case PRODUCT:
- cplx = one; break;
- case VLOOP:
- if (!silent)
- fprintf(stdout, "%5.5s =", index->name);
- break;
- }
-
- idxval = &index->u.val.real;
- index->u.val.imag = 0.0;
-
- for (; *idxval <= to; (*idxval)++)
- switch (how)
- {
- case SUMMATION:
- cplx = cadd(cplx,eval_tree(expr));
- break;
- case PRODUCT:
- cplx = cmul(cplx,eval_tree(expr));
- break;
- case VLOOP:
- cplx = eval_tree(expr);
- if (!silent) {
- fprintf(stdout, "\t%5lg ", *idxval);
- cprin(stdout, NULL, "\n", cplx);
- }
- break;
- case LOOP:
- cplx = eval_tree(expr);
-
- }
-
- return cplx;
-
- }
- }
- }
- }
-
- switch (how) /* got here, so a mistake somewhere */
- {
- case SUMMATION: mode = "Sum"; break;
- case PRODUCT: mode = "Prod"; break;
- case LOOP: mode = "every"; break;
- case VLOOP: mode = "vevery"; break;
- }
-
- execerror("invalid usage of special function", mode);
- }
-
-
- Complex spec_sum(al) /* do summation */
- ArgList *al;
- {
- return iterate(al,SUMMATION);
- }
-
-
- Complex spec_prod(al) /* do product */
- ArgList *al;
- {
- return iterate(al,PRODUCT);
- }
-
-
- Complex spec_every(al) /* do loop */
- ArgList *al;
- {
- return iterate(al,LOOP);
- }
-
- Complex spec_vevery(al) /* do verbose loop */
- ArgList *al;
- {
- return iterate(al,VLOOP);
- }
-
-
- /*
- * multi() is a special function that takes any number of expressions
- * as arguments and evaluates them from left to right. It was added
- * to make certain operations possible from user-functions.
- */
- Complex spec_multi(al)
- ArgList *al;
- {
- while (al) /* uses recursion to step through expressions */
- {
- (void)spec_multi(al->next);
- return eval_tree(al->node);
- }
- }
-
-
- static Complex spec_extreme(al,cmp,what) /* maximum of Re(arg) in arg-list */
- ArgList *al;
- double (*cmp)();
- char *what; /* ascii string containing name of op */
- {
- Complex mval, tval;
-
- if (al) /* called with arguments */
- {
- mval = eval_tree(al->node);
- mval.imag = 0.0;
-
- al = al->next;
-
- while (al)
- {
- tval = eval_tree(al->node);
- mval.real = cmp(mval.real, tval.real);
- al = al->next;
- }
-
- return mval;
- }
-
- execerror("invalid usage of special function", what);
- }
-
- static double fnmax(a, b)
- double a, b;
- { return max(a,b); }
-
- Complex spec_max(al) /* return max of Re(arg) */
- ArgList *al;
- { return spec_extreme(al, fnmax, "max"); }
-
-
- static double fnmin(a, b)
- double a, b;
- { return min(a,b); }
-
- Complex spec_min(al) /* return min of Re(arg) */
- ArgList *al;
- { return spec_extreme(al, fnmin, "min"); }
-
-