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

  1. /*
  2. *    icalc - complex-expression parser
  3. *
  4. *    Special functions for icalc, such as sum, prod etc.
  5. *
  6. *    (C) Martin W Scott, 1991.
  7. */
  8.  
  9. #include <stdio.h>
  10. #include "complex.h"
  11. #include "constant.h"
  12. #include "complex.tab.h"
  13.  
  14. extern int silent;
  15.  
  16. #define SUMMATION    1
  17. #define PRODUCT        2
  18. #define LOOP        3
  19. #define VLOOP        4    /* (verbose loop) */
  20.  
  21. /*
  22. *    General iteration function.
  23. *
  24. *    Used for sums, products and general iteration.
  25. *
  26. */
  27. static Complex iterate(al,how)
  28.     ArgList *al;        /* argument list */
  29.     int how;        /* sum, product or loop */
  30. {
  31.     Node *expr;        /* expression to iterate */
  32.     Symbol *index;        /* index to iterate over */
  33.     double *idxval, to;    /* real part of index, what to iterate upto */
  34.     char *mode;        /* mode as string, for error message */
  35.     Complex cplx;        /* general purpose complex variable */
  36.  
  37.  
  38.     if (al)            /* agruments were passed */
  39.     {
  40.         expr = al->node;    /* get expression to iterate */
  41.  
  42.         if (al = al->next)    /* get upper limit */
  43.         {
  44.             cplx = cinteger(eval_tree(al->node));
  45.             to = cplx.real;
  46.  
  47.             if ((al = al->next) && !al->next) /* get index... */
  48.             {                  /* no more args? */
  49.                 (void)eval_tree(al->node);
  50.                 if (al->node->type == '=' || al->node->type == VAR)
  51.                 {
  52.                     index = al->node->contents.sym;
  53.  
  54.                     if (index->type != VAR)    /* undefined */
  55.                         index->type = VAR;
  56.  
  57.                     switch (how)    /* initial */
  58.                     {
  59.                         case SUMMATION:
  60.                             cplx = zero; break;
  61.                         case PRODUCT:
  62.                             cplx = one; break;
  63.                         case VLOOP:
  64.                             if (!silent)
  65.                                 fprintf(stdout, "%5.5s =", index->name);
  66.                             break;
  67.                     }
  68.  
  69.                     idxval = &index->u.val.real;
  70.                     index->u.val.imag = 0.0;
  71.  
  72.                         for (; *idxval <= to; (*idxval)++) 
  73.                         switch (how)
  74.                         {
  75.                         case SUMMATION:
  76.                             cplx = cadd(cplx,eval_tree(expr));
  77.                             break;
  78.                         case PRODUCT:
  79.                             cplx = cmul(cplx,eval_tree(expr));
  80.                             break;
  81.                         case VLOOP:
  82.                             cplx = eval_tree(expr);
  83.                             if (!silent) {
  84.                                 fprintf(stdout, "\t%5lg  ", *idxval);
  85.                                 cprin(stdout, NULL, "\n", cplx);
  86.                             }
  87.                             break;
  88.                         case LOOP:
  89.                             cplx = eval_tree(expr);
  90.  
  91.                         }
  92.  
  93.                     return cplx;
  94.                     
  95.                 }
  96.             }
  97.         }
  98.     }
  99.  
  100.     switch (how)    /* got here, so a mistake somewhere */
  101.     {
  102.         case SUMMATION:    mode = "Sum"; break;
  103.         case PRODUCT:    mode = "Prod"; break;
  104.         case LOOP:    mode = "every"; break;
  105.         case VLOOP:    mode = "vevery"; break;
  106.     }
  107.  
  108.     execerror("invalid usage of special function", mode);
  109. }
  110.  
  111.  
  112. Complex spec_sum(al)        /* do summation */
  113.     ArgList *al;
  114. {
  115.     return iterate(al,SUMMATION);
  116. }
  117.  
  118.  
  119. Complex spec_prod(al)        /* do product */
  120.     ArgList *al;
  121. {
  122.     return iterate(al,PRODUCT);
  123. }
  124.  
  125.  
  126. Complex spec_every(al)        /* do loop */
  127.     ArgList *al;
  128. {
  129.     return iterate(al,LOOP);
  130. }
  131.  
  132. Complex spec_vevery(al)        /* do verbose loop */
  133.     ArgList *al;
  134. {
  135.     return iterate(al,VLOOP);
  136. }
  137.  
  138.  
  139. /*
  140. *    multi() is a special function that takes any number of expressions
  141. *    as arguments and evaluates them from left to right. It was added
  142. *    to make certain operations possible from user-functions.
  143. */
  144. Complex spec_multi(al)
  145.     ArgList *al;
  146. {
  147.     while (al)    /* uses recursion to step through expressions */
  148.     {
  149.         (void)spec_multi(al->next);
  150.         return eval_tree(al->node);
  151.     }
  152. }
  153.  
  154.  
  155. static Complex spec_extreme(al,cmp,what)    /* maximum of Re(arg) in arg-list */
  156.     ArgList *al;
  157.     double (*cmp)();
  158.     char *what;        /* ascii string containing name of op */
  159. {
  160.     Complex mval, tval;
  161.  
  162.     if (al)        /* called with arguments */
  163.     {
  164.         mval = eval_tree(al->node);
  165.         mval.imag = 0.0;
  166.  
  167.         al = al->next;
  168.  
  169.         while (al)
  170.         {
  171.             tval = eval_tree(al->node);
  172.             mval.real = cmp(mval.real, tval.real);
  173.             al = al->next;
  174.         }
  175.  
  176.         return mval;
  177.     }
  178.  
  179.     execerror("invalid usage of special function", what);
  180. }
  181.  
  182. static double fnmax(a, b)
  183.     double a, b;
  184. { return max(a,b); }
  185.  
  186. Complex spec_max(al)        /* return max of Re(arg) */
  187.     ArgList *al;
  188. { return spec_extreme(al, fnmax, "max"); }
  189.  
  190.  
  191. static double fnmin(a, b)
  192.     double a, b;
  193. { return min(a,b); }
  194.  
  195. Complex spec_min(al)        /* return min of Re(arg) */
  196.     ArgList *al;
  197. { return spec_extreme(al, fnmin, "min"); }
  198.  
  199.