"Fossies" - the Fresh Open Source Software Archive

Member "mapm_4.9.5a/calc.c" (21 Feb 2010, 15790 Bytes) of package /linux/misc/old/mapm-4.9.5a.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "calc.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* 
    3  *  M_APM  -  calc.c
    4  *
    5  *  Copyright (C) 1999 - 2007   Michael C. Ring
    6  *
    7  *  Permission to use, copy, and distribute this software and its
    8  *  documentation for any purpose with or without fee is hereby granted,
    9  *  provided that the above copyright notice appear in all copies and
   10  *  that both that copyright notice and this permission notice appear
   11  *  in supporting documentation.
   12  *
   13  *  Permission to modify the software is granted. Permission to distribute
   14  *  the modified code is granted. Modifications are to be distributed by
   15  *  using the file 'license.txt' as a template to modify the file header.
   16  *  'license.txt' is available in the official MAPM distribution.
   17  *
   18  *  This software is provided "as is" without express or implied warranty.
   19  */
   20 
   21 /*
   22  *      $Id: calc.c,v 1.25 2007/12/03 02:04:04 mike Exp $
   23  *
   24  *      RPN Calculator : demo of the MAPM math library
   25  *
   26  *      $Log: calc.c,v $
   27  *      Revision 1.25  2007/12/03 02:04:04  mike
   28  *      update version
   29  *
   30  *      Revision 1.24  2007/12/03 01:16:21  mike
   31  *      Update license
   32  *
   33  *      Revision 1.23  2004/05/31 22:47:55  mike
   34  *      added MOD operator
   35  *
   36  *      Revision 1.22  2003/05/31 22:44:19  mike
   37  *      update version for display
   38  *
   39  *      Revision 1.21  2003/05/15 21:21:16  mike
   40  *      add MAPM version to output
   41  *
   42  *      Revision 1.20  2002/11/03 22:59:11  mike
   43  *      Updated function parameters to use the modern style
   44  *
   45  *      Revision 1.19  2001/09/03 17:20:45  mike
   46  *      make new fixpt string call more intuitive
   47  *
   48  *      Revision 1.18  2001/08/26 22:55:58  mike
   49  *      use fixed point format if the exponent of the result is -4 -> +6
   50  *
   51  *      Revision 1.17  2001/07/16 18:51:42  mike
   52  *      add call to free_all_mem
   53  *
   54  *      Revision 1.16  2001/07/15 21:00:58  mike
   55  *      add GCD and LCM
   56  *
   57  *      Revision 1.15  2001/03/25 21:59:20  mike
   58  *      add floor and ceil functions
   59  *
   60  *      Revision 1.14  2001/02/06 21:52:54  mike
   61  *      use internal reciprocal function now
   62  *
   63  *      Revision 1.13  2000/08/04 00:37:39  mike
   64  *      remove unneeded int from calc_square
   65  *
   66  *      Revision 1.12  2000/08/03 18:05:12  mike
   67  *      add help for new memory commands
   68  *
   69  *      Revision 1.11  2000/08/03 17:56:38  mike
   70  *      add memory capability
   71  *
   72  *      Revision 1.10  2000/07/11 23:20:19  mike
   73  *      calculate 'pi' using the new AGM library function
   74  *
   75  *      Revision 1.9  2000/05/05 20:21:14  mike
   76  *      compute PI on the fly if more than 115 decimal
   77  *      places are asked for.
   78  *
   79  *      Revision 1.8  2000/04/03 18:51:25  mike
   80  *      added operators cube root and hyperbolic sin, cos, tan
   81  *      with their inverses
   82  *
   83  *      Revision 1.7  2000/02/03 22:43:03  mike
   84  *      calculate a few extra decimal places on the
   85  *      intermediate results so all answers on the
   86  *      final output stay consistent
   87  *
   88  *      Revision 1.6  1999/07/05 15:06:04  mike
   89  *      added DUP operator
   90  *
   91  *      Revision 1.5  1999/06/01 02:35:00  mike
   92  *      fix isdigit call with cast
   93  *
   94  *      Revision 1.4  1999/05/28 21:17:11  mike
   95  *      break up usage into 2 printf so dos compile doesnt choke
   96  *
   97  *      Revision 1.3  1999/05/19 02:29:44  mike
   98  *      added version of calc to usage line
   99  *
  100  *      Revision 1.2  1999/05/19 02:18:33  mike
  101  *      added check for stack under-flow
  102  *
  103  *      Revision 1.1  1999/05/19 02:01:02  mike
  104  *      Initial revision
  105  */
  106 
  107 #include <stdio.h>
  108 #include <stdlib.h>
  109 #include <string.h>
  110 #include <ctype.h>
  111 #include "m_apm.h"
  112 
  113 /*  prototypes for functions in this file  */
  114 
  115 void     calc_square(M_APM, M_APM);
  116 void     calc_mod(M_APM, M_APM, M_APM);
  117 void     calc_pi(M_APM, int);
  118 char     *lowercase(char *);
  119 
  120 char     *out_buffer;
  121 char     in_buffer[8192];
  122 
  123 #define  STACK_SIZE 96
  124 
  125 M_APM    calc_stack_data[STACK_SIZE];
  126 M_APM    memory_data[36];
  127 
  128 #define NUM_OPERATOR_ENTRIES 41          /* number of operators */
  129 
  130 /* calling convention for various MAPM library functions ... */
  131 
  132 #define MMM     0x0A01                   /*  ( MAPM, MAPM, MAPM )       */
  133 #define MiMM    0x0A02                   /*  ( MAPM, int, MAPM, MAPM )  */
  134 #define MiM     0x0A03                   /*  ( MAPM, int, MAPM )        */
  135 #define Mi      0x0A04                   /*  ( MAPM, int )              */
  136 #define MM      0x0A05                   /*  ( MAPM, MAPM )             */
  137 #define MXY     0x0A80                   /*  special for x <> y         */
  138 #define MDUP    0x0A81                   /*  special for dup            */
  139 #define M_END   0x0AFF                   /*  end of table flag          */
  140 
  141 struct  opstr {
  142   char  operator[16];      
  143   int   calling_convention;
  144   void  (*funcname)();
  145 };
  146 
  147 struct  opstr  operator_lookup[NUM_OPERATOR_ENTRIES] = {  
  148    {  "+",    MMM,     m_apm_add,             /*   0   */  },
  149    {  "-",    MMM,     m_apm_subtract,        /*   1   */  },
  150    {  "*",    MMM,     m_apm_multiply,        /*   2   */  },
  151    {  "x",    MMM,     m_apm_multiply,        /*   3   */  },
  152    {  "/",    MiMM,    m_apm_divide,          /*   4   */  },
  153    {  "\\",   MMM,     m_apm_integer_divide,  /*   5   */  },
  154    {  "i",    MMM,     m_apm_integer_divide,  /*   6   */  },
  155    {  "!",    MM,      m_apm_factorial,       /*   7   */  },
  156    {  "s",    MiM,     m_apm_sin,             /*   8   */  },
  157    {  "c",    MiM,     m_apm_cos,             /*   9   */  },
  158    {  "t",    MiM,     m_apm_tan,             /*  10   */  },
  159    {  "q",    MiM,     m_apm_sqrt,            /*  11   */  },
  160    {  "as",   MiM,     m_apm_asin,            /*  12   */  },
  161    {  "ac",   MiM,     m_apm_acos,            /*  13   */  },
  162    {  "at",   MiM,     m_apm_atan,            /*  14   */  },
  163    {  "at2",  MiMM,    m_apm_atan2,           /*  15   */  },
  164    {  "lg",   MiM,     m_apm_log,             /*  16   */  },
  165    {  "lg10", MiM,     m_apm_log10,           /*  17   */  },
  166    {  "e",    MiM,     m_apm_exp,             /*  18   */  },
  167    {  "p",    MiMM,    m_apm_pow,             /*  19   */  },
  168    {  "h",    MM,      m_apm_negate,          /*  20   */  },
  169    {  "n",    MM,      m_apm_negate,          /*  21   */  },
  170    {  "xy",   MXY,     NULL,                  /*  22   */  },
  171    {  "d",    MDUP,    NULL,                  /*  23   */  },
  172    {  "r",    MiM,     m_apm_reciprocal,      /*  24   */  },
  173    {  "x2",   MM,      calc_square,           /*  25   */  },
  174    {  "pi",   Mi,      calc_pi,               /*  26   */  },
  175    {  "hs",   MiM,     m_apm_sinh,            /*  27   */  },
  176    {  "hc",   MiM,     m_apm_cosh,            /*  28   */  },
  177    {  "ht",   MiM,     m_apm_tanh,            /*  29   */  },
  178    {  "has",  MiM,     m_apm_asinh,           /*  30   */  },
  179    {  "hac",  MiM,     m_apm_acosh,           /*  31   */  },
  180    {  "hat",  MiM,     m_apm_atanh,           /*  32   */  },
  181    {  "b",    MiM,     m_apm_cbrt,            /*  33   */  },
  182    {  "f",    MM,      m_apm_floor,           /*  34   */  },
  183    {  "cl",   MM,      m_apm_ceil,            /*  35   */  },
  184    {  "gcd",  MMM,     m_apm_gcd,             /*  36   */  },
  185    {  "lcm",  MMM,     m_apm_lcm,             /*  37   */  },
  186    {  "mod",  MMM,     calc_mod,              /*  38   */  },
  187    {  "%",    MMM,     calc_mod,              /*  39   */  },
  188    {  "ZZZ",  M_END,   NULL                   /*  40   */  }
  189  }; 
  190 
  191 
  192 int main(int argc, char *argv[])
  193 {
  194 void     (*fp)();
  195 char     ch0, ch1, *cp, version_info[80];
  196 int      ii, ilow, stack_pointer, decimal_places, k,
  197      index, len, memory_ref[36];
  198 M_APM    apmtmp;
  199 M_APM    arg1;   
  200 M_APM    arg2;
  201 
  202 if (argc < 2)
  203   {
  204    m_apm_lib_short_version(version_info);
  205 
  206    fprintf(stderr,"calc [-d##] <numbers,operators>\t\t\t\t[Version 2.3]\n");
  207    fprintf(stderr,
  208    "      -d : specify decimal places, default = 30\t\t[MAPM Version %s]\n\n",
  209            version_info);
  210 
  211    fprintf(stderr,
  212 "operators :  + : add                           s : sin\n\
  213              - : subtract                      c : cos\n\
  214              x : multiply (*)                  t : tan\n\
  215              / : divide                        q : sqrt\n\
  216              \\ : integer divide (i)           as : arc-sin\n\
  217              ! : factorial                    ac : arc-cos\n");
  218 
  219    fprintf(stderr,
  220 "            x2 : x ^ 2                        at : arc-tan\n\
  221              r : 1 / x                       at2 : arc-tan2 (y,x)\n\
  222             lg : log                           e : e ^ x\n\
  223           lg10 : log10                         p : y ^ x\n\
  224             xy : x<>y (exchange x,y)           n : +/- (negate (h))\n");
  225 
  226    fprintf(stderr,
  227 "            hs : sinh                        has : arc-sinh\n\
  228             hc : cosh                        hac : arc-cosh\n\
  229             ht : tanh                        hat : arc-tanh\n\
  230              b : cube root                     d : dup (HP-Enter)\n");
  231 
  232    fprintf(stderr,
  233 "             f : floor                        cl : ceil\n\
  234            gcd : GCD                         lcm : LCM\n\
  235             s# : save memory, # = 0-9,a-z     r# : recall memory, # = 0-9,a-z\n\
  236             pi : 3.14159..                   mod : modulus (%%)\n");
  237 
  238    exit(2);
  239   }
  240 
  241 /* leave arg1, arg2 uninitialized on purpose */
  242 /*                                           */
  243 /* analagous to  :   int  *arg1, buffer[NN]; */
  244 /*                   arg1 = buffer;          */
  245 
  246 apmtmp = m_apm_init();
  247 
  248 for (k=0; k < STACK_SIZE; k++)
  249   calc_stack_data[k] = m_apm_init();
  250 
  251 for (k=0; k < 36; k++)
  252   {
  253    memory_data[k] = m_apm_init();
  254    memory_ref[k]  = 0;
  255   }
  256 
  257 /*
  258  *   normally, stack_pointer would be 0 and we would 
  259  *   check all operations on it to verify it never 
  260  *   went < 0. since this is a just demo program and not
  261  *   a 'real' application, we will just warn the user
  262  *   at the end if a potential stack underflow occurred.
  263  *   we can likely force a run-time core dump with 16 
  264  *   math operations with no numbers to work with :
  265  *   i.e. -> calc + + + + ... 16 times
  266  */
  267 
  268 stack_pointer  = 16;
  269 decimal_places = 30;
  270 ilow           = 1;
  271 
  272 strcpy(in_buffer, argv[1]);
  273 lowercase(in_buffer);
  274 if ((cp = strstr(in_buffer,"-d")) != NULL)
  275   {
  276    ilow++;
  277    cp += 2;
  278    decimal_places = atoi(cp);
  279    if (decimal_places < 2)
  280      decimal_places = 2;
  281   }
  282 
  283 for (ii=ilow; ii < argc; ii++)
  284   {
  285    strcpy(in_buffer, argv[ii]);
  286    lowercase(in_buffer);
  287    k = 0;
  288 
  289    while (1)
  290      {        
  291       /*
  292        *  if the first char is a digit, we assume this is a number 
  293        */
  294 
  295       if (k == 0)
  296         {
  297          if (isdigit((int)*in_buffer))
  298            {
  299         stack_pointer++;
  300         m_apm_set_string(calc_stack_data[stack_pointer], in_buffer);
  301         break;
  302        }
  303     }
  304 
  305       /* 
  306        *  at end of operator table ??    if so, see if we have
  307        *  a memory operator. if not, assume this is a number.
  308        */
  309 
  310       if (operator_lookup[k].calling_convention == M_END)
  311         {
  312      /*
  313       *  see if we have a 'memory' operator
  314       */
  315 
  316      len = strlen(in_buffer);
  317      ch0 = in_buffer[0];
  318      ch1 = in_buffer[1];
  319 
  320      if (ch0 == 's' || ch0 == 'r')
  321        {
  322         /*  s[0-9,a-z]   or  r[0-9,a-z]  */
  323 
  324             index = -1;
  325       
  326             if (ch1 >= '0' && ch1 <= '9')
  327               index = (int)ch1 - '0';
  328       
  329             if (ch1 >= 'a' && ch1 <= 'z')
  330               index = (int)ch1 + 10 - 'a';
  331 
  332             if (len == 2 && index >= 0)
  333           {
  334            if (ch0 == 'r')     /* re-call memory */
  335              {
  336           if (memory_ref[index] != 0)
  337             {
  338                  stack_pointer++;
  339                  arg1 = memory_data[index];
  340                  m_apm_copy(calc_stack_data[stack_pointer], arg1);
  341             }
  342           else
  343             {
  344                fprintf(stderr,
  345     "Warning!, Using un-initialized memory location : \'%c\'\n",ch1);
  346             }
  347          }
  348                else                /* store memory   */
  349              {
  350               arg1 = memory_data[index];
  351               m_apm_copy(arg1, calc_stack_data[stack_pointer]);
  352           memory_ref[index] = 1;
  353          }
  354           }
  355             else
  356           {
  357                fprintf(stderr,
  358     "Error!, Memory command error : Syntax  s[0-9,a-z] or r[0-9,a-z]\n");
  359            exit(4);
  360               }
  361        }
  362          else     /* assume this is a number */
  363        {
  364         stack_pointer++;
  365         m_apm_set_string(calc_stack_data[stack_pointer], in_buffer);
  366        }
  367 
  368      break;
  369     }
  370 
  371       if (strcmp(operator_lookup[k].operator, in_buffer) == 0)
  372         {
  373          /*
  374           *  we found an operator, so do it 
  375           */
  376 
  377      if (operator_lookup[k].calling_convention == Mi)
  378        {
  379             fp = operator_lookup[k].funcname;
  380             (*fp)(apmtmp, (decimal_places + 6));
  381         m_apm_copy(calc_stack_data[++stack_pointer], apmtmp);
  382        }
  383     
  384      if (operator_lookup[k].calling_convention == MXY)
  385        {
  386         arg2 = calc_stack_data[stack_pointer - 1];
  387         arg1 = calc_stack_data[stack_pointer];
  388 
  389         m_apm_copy(apmtmp, arg1);
  390         m_apm_copy(arg1, arg2);
  391         m_apm_copy(arg2, apmtmp);
  392        }
  393     
  394      if (operator_lookup[k].calling_convention == MDUP)
  395        {
  396         arg1 = calc_stack_data[stack_pointer];
  397         m_apm_copy(calc_stack_data[++stack_pointer], arg1);
  398        }
  399     
  400      if (operator_lookup[k].calling_convention == MMM)
  401        {
  402             fp   = operator_lookup[k].funcname;
  403         arg2 = calc_stack_data[stack_pointer];
  404         arg1 = calc_stack_data[--stack_pointer];
  405             (*fp)(apmtmp, arg1, arg2);
  406         m_apm_copy(arg1, apmtmp);
  407        }
  408     
  409      if (operator_lookup[k].calling_convention == MiMM)
  410        {
  411             fp   = operator_lookup[k].funcname;
  412         arg2 = calc_stack_data[stack_pointer];
  413         arg1 = calc_stack_data[--stack_pointer];
  414             (*fp)(apmtmp, (decimal_places + 6), arg1, arg2);
  415         m_apm_copy(arg1, apmtmp);
  416        }
  417     
  418      if (operator_lookup[k].calling_convention == MM)
  419        {
  420             fp   = operator_lookup[k].funcname;
  421         arg1 = calc_stack_data[stack_pointer];
  422             (*fp)(apmtmp, arg1);
  423         m_apm_copy(arg1, apmtmp);
  424        }
  425     
  426      if (operator_lookup[k].calling_convention == MiM)
  427        {
  428             fp   = operator_lookup[k].funcname;
  429         arg1 = calc_stack_data[stack_pointer];
  430             (*fp)(apmtmp, (decimal_places + 6), arg1);
  431         m_apm_copy(arg1, apmtmp);
  432        }
  433 
  434      break;
  435     }
  436 
  437       k++;
  438      }
  439   }
  440 
  441 if (stack_pointer <= 16)
  442   {
  443    fprintf(stderr,"Warning!, stack under-flow, result is unreliable\n");
  444   }
  445 
  446 arg1 = calc_stack_data[stack_pointer];
  447 m_apm_round(apmtmp, decimal_places, arg1);
  448 
  449 /*
  450  *  if the exponent is >= -4 && <= 6,
  451  *  use the fixed point format 
  452  */
  453 
  454 k = m_apm_exponent(apmtmp);
  455 if (k >= -4 && k <= 6)
  456   {
  457    out_buffer = m_apm_to_fixpt_stringexp(-1, apmtmp, '.', 0, 0);
  458   }
  459 else
  460   {
  461    out_buffer = (char *)malloc(decimal_places + 16);
  462 
  463    if (out_buffer != NULL)
  464      {
  465       m_apm_to_string(out_buffer, -1, apmtmp);
  466      }
  467   }
  468 
  469 if (out_buffer == NULL)
  470   {
  471    fprintf(stderr,"calc: out of memory\n");
  472    exit(4);
  473   }
  474 
  475 printf("%s\n",out_buffer);
  476 
  477 for (k=0; k < STACK_SIZE; k++)
  478   m_apm_free(calc_stack_data[k]);
  479 
  480 for (k=0; k < 36; k++)
  481   m_apm_free(memory_data[k]);
  482 
  483 m_apm_free(apmtmp);
  484 m_apm_free_all_mem();
  485 
  486 free(out_buffer);
  487 
  488 exit(0);
  489 }
  490 /***********************************************************************/
  491 void     calc_square(M_APM rr, M_APM xx)
  492 {
  493 m_apm_multiply(rr, xx, xx);
  494 }
  495 /***********************************************************************/
  496 void     calc_mod(M_APM mm, M_APM aa, M_APM bb)
  497 {
  498 M_APM    qq;
  499 
  500 qq = m_apm_init();
  501 
  502 m_apm_integer_div_rem(qq, mm, aa, bb);
  503 
  504 m_apm_free(qq);
  505 }
  506 /***********************************************************************/
  507 void     calc_pi(M_APM rr, int p)
  508 {
  509 M_APM    aa;
  510 
  511 if (p > 115)
  512   {
  513    aa = m_apm_init();
  514 
  515    /* compute : PI = 2 * asin(1) */
  516 
  517    m_apm_asin(aa, (p + 2), MM_One);
  518    m_apm_add(rr, aa, aa);
  519 
  520    m_apm_free(aa);
  521   }
  522 else
  523   m_apm_round(rr, p, MM_PI);
  524 }
  525 /***********************************************************************/
  526 char    *lowercase(char *s)
  527 {
  528 char    *p;
  529 
  530 p = s;
  531 while (1)
  532   {
  533    if (*p >= 'A' && *p <= 'Z')  *p += 'a' - 'A';
  534    if (*p++ == 0)  break;
  535   }
  536 return(s);
  537 }
  538 /***********************************************************************/