home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Otherware
/
Otherware_1_SB_Development.iso
/
amiga
/
misc
/
icalc.lzh
/
icalc
/
src
/
special.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-26
|
4KB
|
199 lines
/*
* 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"); }