home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / misc / eval / source / src.lha / funcs.c < prev    next >
C/C++ Source or Header  |  1993-04-13  |  13KB  |  427 lines

  1. /*
  2. **
  3. ** FUNCS.C     A module to be included with EVAL.C that handles
  4. **             the manipulation of functions.
  5. **
  6. ** Originally written 5/89 in ANSI C
  7. **
  8. ** To add/change the functions in Eval:
  9. ** --------------------------------------------------------------
  10. ** 1. If the name of your function is longer than MAXFLEN, or the
  11. **    argument list string is longer than MAXALEN, then increase the
  12. **    size of these defines (MAXFLEN in eval.h, MAXALEN in funcs.c).
  13. ** 1. Update the value of NUMFUNCS in eval.h (total number of functions).
  14. ** 2. Add a #define for any new functions to the list of #defines
  15. **    below.  You do not need to keep the list in alphabetic order.
  16. ** 3. Add the function ID (#define tag), name, argument list, and a
  17. **    brief descripton to the flist[] array below.  Please keep the list
  18. **    in alphabetic order by function name.
  19. ** 4. Add the actual function code to the func_eval function below.
  20. **    Follow the examples of other functions.
  21. ** 5. If necessary, add the C-code for new math functions to emath.c,
  22. **    and add prototypes for new C math functions to eval.h
  23. **    NOTICE:  Read the disclaimer about adding code to emath.c in
  24. **             the comments of emath.c.
  25. ** 6. Recompile ALL modules.
  26. **
  27. **
  28. ** Eval is a floating point expression evaluator.
  29. ** This file last updated in version 1.12
  30. ** For the version number, see eval.h
  31. ** Copyright (C) 1993  Will Menninger
  32. **
  33. ** This program is free software; you can redistribute it and/or modify it
  34. ** under the terms of the GNU General Public License as published by the
  35. ** Free Software Foundation; either version 2 of the License, or any
  36. ** later version.
  37. **
  38. ** This program is distributed in the hope that it will be useful, but
  39. ** WITHOUT ANY WARRANTY; without even the implied warranty of
  40. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  41. ** General Public License for more details.
  42. **
  43. ** You should have received a copy of the GNU General Public License along
  44. ** with this program; if not, write to the Free Software Foundation, Inc.,
  45. ** 675 Mass Ave, Cambridge, MA 02139, USA.
  46. **
  47. ** The author until 9/93 can be contacted at:
  48. ** e-mail:     willus@ilm.pfc.mit.edu
  49. ** U.S. mail:  Will Menninger, 45 River St., #2, Boston, MA 02108-1124
  50. **
  51. */
  52.  
  53. #include   "eval.h"
  54.  
  55. #define MAXALEN     3
  56. #define MAXDLEN     80
  57.  
  58. typedef struct {
  59.                int     id;
  60.                char    name[MAXFLEN+1];
  61.                char    argspec[MAXALEN+1];
  62.                char    desc[MAXDLEN+1];
  63.                } FUNC, *FUNCPTR;
  64.  
  65. #define    ABSVAL      1
  66. #define    ACOS        2
  67. #define    ACOSH       3
  68. #define    ASIN        4
  69. #define    ASINH       5
  70. #define    ATAN        6
  71. #define    ATAN2       7
  72. #define    ATANH       8
  73. #define    BESSI       9
  74. #define    BESSJ       10
  75. #define    BESSK       11
  76. #define    CEIL        12
  77. #define    COS         13
  78. #define    COSH        14
  79. #define    DBESSI      15
  80. #define    DBESSJ      16
  81. #define    DBESSK      17
  82. #define    DJROOT      18
  83. #define    EXP         19
  84. #define    FACT        20
  85. #define    FLOOR       21
  86. #define    JROOT       22
  87. #define    LN          23
  88. #define    LOG         24
  89. #define    SIGN        25
  90. #define    SIN         26
  91. #define    SINH        27
  92. #define    SQRT        28
  93. #define    TAN         29
  94. #define    TANH        30
  95.  
  96. static FUNC    flist[NUMFUNCS] =
  97. {
  98. {ABSVAL,"abs",    "x",  "absolute value"                              },
  99. {ACOS,  "acos",   "x",  "arccosine, return value in radians"          },
  100. {ACOSH, "acosh",  "x",  "inverse hyperbolic cosine"                   },
  101. {ASIN,  "asin",   "x",  "arcsine, return value in radians"            },
  102. {ASINH, "asinh",  "x",  "inverse hyperbolic sine"                     },
  103. {ATAN,  "atan",   "x",  "arctangent, return value in radians"         },
  104. {ATAN2, "atan2",  "y,x","arctangent of y/x, return value in radians"  },
  105. {ATANH, "atanh",  "x",  "inverse hyperbolic tangent"                  },
  106. {BESSI, "bessi",  "m,x","bessel function Im(x)"                       },
  107. {BESSJ, "bessj",  "m,x","bessel function Jm(x)"                       },
  108. {BESSK, "bessk",  "m,x","bessel function Km(x)"                       },
  109. {CEIL,  "ceil",   "x",  "round up"                                    },
  110. {COS,   "cos",    "x",  "cosine, x in radians"                        },
  111. {COSH,  "cosh",   "x",  "hyperbolic cosine"                           },
  112. {DBESSI,"dbessi", "m,x","derivative of bessel function:  Im'(x)"      },
  113. {DBESSJ,"dbessj", "m,x","derivative of bessel function:  Jm'(x)"      },
  114. {DBESSK,"dbessk", "m,x","derivative of bessel function:  Km'(x)"      },
  115. {DJROOT,"djroot", "m,n","nth non-zero root of Jm'(x)"                 },
  116. {EXP,   "exp",    "x",  "e (2.718..) raised to the power of x"        },
  117. {FACT,  "fact",   "n",  "factorial (n!)"                              },
  118. {FLOOR, "floor",  "x",  "round down"                                  },
  119. {JROOT, "jroot",  "m,n","nth non-zero root of Jm(x)"                  },
  120. {LN,    "ln",     "x",  "natural logarithm (base e)"                  },
  121. {LOG,   "log",    "x",  "logarithm to the base 10"                    },
  122. {SIGN,  "sgn",    "x",  "-1 if x<0, 0 if x=0, +1 if x>0"              },
  123. {SIN,   "sin",    "x",  "sine, x in radians"                          },
  124. {SINH,  "sinh",   "x",  "hyperbolic sine"                             },
  125. {SQRT,  "sqrt",   "x",  "squareroot"                                  },
  126. {TAN,   "tan",    "x",  "tangent, x in radians"                       },
  127. {TANH,  "tanh",   "x",  "hyperbolic tangent"                          }
  128. };
  129.  
  130.  
  131. static BOOLEAN func_error(int,int);
  132. static int     maxfunclen(FUNCPTR);
  133.  
  134. /*
  135. ** print_funclist(FILE *s,char *input,int d)
  136. **
  137. ** Prints a list of the functions
  138. **
  139. */
  140. int print_funclist(FILE *s,char *input,int d)
  141.  
  142.     {
  143.     char    line[MAXALEN+MAXFLEN+MAXDLEN+10];
  144.     int     i,j,k,l,n,m1,nc,cw,nr,li,c;
  145.  
  146.     m1=maxfunclen(flist)+2;
  147.     cw=m1+2;
  148.     if (d)
  149.         nc=1;
  150.     else
  151.         {
  152.         nc=(SCRWIDTH+3)/cw;
  153.         if (nc<=0)
  154.             nc=1;
  155.         }
  156.     nr=(NUMFUNCS+nc-1)/nc;
  157.     for (i=0;i<nr;i++)
  158.         {
  159.         li=0;
  160.         for (j=0;j<nc;j++)
  161.             {
  162.             k=i+j*nr;
  163.             if (k>=NUMFUNCS)
  164.                 break;
  165.             for (l=0;(c=flist[k].name[l])!=EOS;l++)
  166.                 line[li++]=c;
  167.             line[li++]='(';
  168.             for (l++,n=l;(c=flist[k].argspec[l-n])!=EOS;l++)
  169.                 line[li++]=c;
  170.             line[li++]=')';
  171.             for (l++;l<m1;l++)
  172.                 line[li++]=' ';
  173.             if (d)
  174.                 {
  175.                 for (l=0;l<4;l++)
  176.                     line[li++]=' ';
  177.                 line[li]=EOS;
  178.                 strcat(line,flist[k].desc);
  179.                 li=strlen(line);
  180.                 }
  181.             else
  182.                 if (j<nc-1)
  183.                     for (;l<cw;l++)
  184.                         line[li++]=' ';
  185.             }
  186.         line[li]=EOS;
  187.         printf("%s\n",line);
  188.         if (s==stdin && i!=nr-1 && ((i+3)%NLINES)==0)
  189.             {
  190.             printf("\nPress <ENTER> for more...\n");
  191.             printf("%s",PROMPT);
  192.             input[0]=EOS;
  193.             fgets(input,MAXINPUT,s);
  194.             fixup(input);
  195.             if (input[0]!=EOS)
  196.                 return(1);
  197.             printf("\n");
  198.             }
  199.         }
  200.     printf("\n");
  201.     return(0);
  202.     }
  203.  
  204.  
  205. /*
  206. ** maxfunclen(FUNCPTR flist)
  207. **
  208. ** returns the length of the longest function name plus arguments
  209. ** (used for printing)
  210. **
  211. */
  212.  
  213. static int maxfunclen(FUNCPTR flist)
  214.  
  215.    {
  216.    int     i,len,max;
  217.  
  218.    for (max=strlen(flist[0].name)+strlen(flist[0].argspec),i=1;i<NUMFUNCS;i++)
  219.        if ((len=strlen(flist[i].name)+strlen(flist[i].argspec))>max)
  220.            max=len;
  221.    return(max);
  222.    }
  223.  
  224.  
  225. int func_code(char *s)
  226.  
  227.     {
  228.     int    i,step,c,count;
  229.  
  230.     i=step=NUMFUNCS>>1;
  231.     count=0;
  232.     while (1)
  233.         {
  234.         if (step>1)
  235.             step>>=1;
  236.         else
  237.             {
  238.             count++;
  239.             if (count>5)
  240.                 break;
  241.             }
  242.         if (!(c=strcmp(s,flist[i].name)))
  243.             return(i+1);
  244.         if (c>0)
  245.                 {
  246.                 if (i==NUMFUNCS-1)
  247.                     break;
  248.                 i=i+step;
  249.                 continue;
  250.                 }
  251.         if (i==0)
  252.             break;
  253.         i=i-step;
  254.         }
  255.     return(0);
  256.     }
  257.  
  258.  
  259.  
  260. int func_nargs(int code)
  261.  
  262.     {
  263.     return((int)((strlen(flist[code-1].argspec)+1)/2));
  264.     }
  265.  
  266.  
  267. char *func_name(int code)
  268.  
  269.     {
  270.     return(flist[code-1].name);
  271.     }
  272.  
  273.  
  274. BOOLEAN func_eval(int code,double *args,double *ret_val)
  275.  
  276.     {
  277.     switch (flist[code-1].id)
  278.         {
  279.         case ABSVAL:
  280.             (*ret_val)=fabs(args[0]);
  281.             return(1);
  282.         case ACOS:
  283.             if (args[0]<-1 || args[0]>1)
  284.                 return(func_error(code,0));
  285.             (*ret_val)=acos(args[0]);
  286.             return(1);
  287.         case ACOSH:
  288.             if (args[0]<1)
  289.                 return(func_error(code,0));
  290.             (*ret_val)=acosh(args[0]);
  291.             return(1);
  292.         case ASIN:
  293.             if (args[0]<-1 || args[0]>1)
  294.                 return(func_error(code,0));
  295.             (*ret_val)=asin(args[0]);
  296.             return(1);
  297.         case ASINH:
  298.             (*ret_val)=asinh(args[0]);
  299.             return(1);
  300.         case ATAN:
  301.             (*ret_val)=atan(args[0]);
  302.             return(1);
  303.         case ATAN2:
  304.             (*ret_val)=atan2(args[0],args[1]);
  305.             return(1);
  306.         case ATANH:
  307.             if (args[0]<=-1 || args[0]>=1)
  308.                 return(func_error(code,0));
  309.             (*ret_val)=atanh(args[0]);
  310.             return(1);
  311.         case BESSI:
  312.             if (args[0]!=((int)args[0]))
  313.                 return(func_error(code,1));
  314.             (*ret_val)=bessi((int)args[0],args[1]);
  315.             return(1);
  316.         case BESSJ:
  317.             if (args[0]!=((int)args[0]))
  318.                 return(func_error(code,1));
  319.             (*ret_val)=bessj((int)args[0],args[1]);
  320.             return(1);
  321.         case BESSK:
  322.             if (args[0]!=((int)args[0]))
  323.                 return(func_error(code,1));
  324.             (*ret_val)=bessk((int)args[0],args[1]);
  325.             return(1);
  326.         case CEIL:
  327.             (*ret_val)=ceil(args[0]);
  328.             return(1);
  329.         case COS:
  330.             (*ret_val)=cos(args[0]);
  331.             return(1);
  332.         case COSH:
  333.             (*ret_val)=cosh(args[0]);
  334.             return(1);
  335.         case DBESSI:
  336.             if (args[0]!=((int)args[0]))
  337.                 return(func_error(code,1));
  338.             (*ret_val)=dbessi((int)args[0],args[1]);
  339.             return(1);
  340.         case DBESSJ:
  341.             if (args[0]!=((int)args[0]))
  342.                 return(func_error(code,1));
  343.             (*ret_val)=dbessj((int)args[0],args[1]);
  344.             return(1);
  345.         case DBESSK:
  346.             if (args[0]!=((int)args[0]))
  347.                 return(func_error(code,1));
  348.             (*ret_val)=dbessk((int)args[0],args[1]);
  349.             return(1);
  350.         case DJROOT:
  351.             if (args[0]!=((int)args[0]))
  352.                 return(func_error(code,1));
  353.             if (args[1]!=((int)args[1]) || args[1]<1)
  354.                 return(func_error(code,2));
  355.             (*ret_val)=djroot((int)args[0],(int)args[1]);
  356.             return(1);
  357.         case EXP:
  358.             (*ret_val)=exp(args[0]);
  359.             return(1);
  360.         case FACT:
  361.             if (args[0]<0)
  362.                 return(func_error(code,5));
  363.             if (args[0]!=((int)args[0]))
  364.                 return(func_error(code,3));
  365.             (*ret_val)=factorial((int)args[0]);
  366.             return(1);
  367.         case FLOOR:
  368.             (*ret_val)=floor(args[0]);
  369.             return(1);
  370.         case JROOT:
  371.             if (args[0]!=((int)args[0]))
  372.                 return(func_error(code,1));
  373.             if (args[1]!=((int)args[1]) || args[1]<1)
  374.                 return(func_error(code,2));
  375.             (*ret_val)=jroot((int)args[0],(int)args[1]);
  376.             return(1);
  377.         case LN:
  378.             if (args[0]<=0)
  379.                 return(func_error(code,4));
  380.             (*ret_val)=log(args[0]);
  381.             return(1);
  382.         case LOG:
  383.             if (args[0]<=0)
  384.                 return(func_error(code,4));
  385.             (*ret_val)=log10(args[0]);
  386.             return(1);
  387.         case SIGN:
  388.             (*ret_val)=SGN(args[0]);
  389.             return(1);
  390.         case SIN:
  391.             (*ret_val)=sin(args[0]);
  392.             return(1);
  393.         case SINH:
  394.             (*ret_val)=sinh(args[0]);
  395.             return(1);
  396.         case SQRT:
  397.             if (args[0]<0)
  398.                 return(func_error(code,5));
  399.             (*ret_val)=sqrt(args[0]);
  400.             return(1);
  401.         case TAN:
  402.             (*ret_val)=tan(args[0]);
  403.             return(1);
  404.         case TANH:
  405.             (*ret_val)=tanh(args[0]);
  406.             return(1);
  407.         }
  408.     printf("Unknown function code.\n");
  409.     return(0);
  410.     }
  411.  
  412.  
  413. static BOOLEAN func_error(int code,int error)
  414.  
  415.     {
  416.     static char *error_code[] = {
  417.                 "argument out of range",
  418.                 "first argument must be an integer",
  419.                 "second argument must be a positive integer",
  420.                 "argument must be an integer",
  421.                 "argument must be positive",
  422.                 "argument must be non-negative",
  423.                 };
  424.     printf("%s:  %s.\n",flist[code-1].name,error_code[error]);
  425.     return(0);
  426.     }
  427.