home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / calculat / meval113.zip / SRC / FUNCS.C < prev    next >
Text File  |  1993-04-11  |  12KB  |  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.