home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / calculat / c_calc10.zip / C-CALC.CPP next >
C/C++ Source or Header  |  1993-05-03  |  11KB  |  396 lines

  1. /***************************************************************************
  2. ************************   C-CALC.CPP   ************************************
  3. ****************************************************************************
  4. Version 1.0 of C-CALC.CPP by Joe Spector May 3, 1993.
  5.  
  6. Freeware.
  7.  
  8. Complex Number Calculator:
  9.  
  10.   CopyJoe policy:
  11.      You can do anything they like with the program or source code
  12.      except sell it or any part of it.
  13.  
  14.   This program has been tested using Borland C++ 3.1
  15.  
  16.   Motivation for c-calc:
  17.      To allow simple evaluation of complex number expressions where
  18.      the complex numbers may be entered in polar or xy notation or
  19.      combinations of the two.
  20.  
  21.      e.g.
  22.  
  23.      to evaluate this
  24.  
  25.         (1.2 + 1.4i)(4*exp(2.3i))
  26.        ---------------------------
  27.         1 + 2.3j + 4exp(0.3i)
  28.  
  29.  
  30.      the user would type in the following:
  31.  
  32.      1.2,1.4            <---   ,  means entered as xy
  33.      4d2.3              <---   d  means polar (in degrees)
  34.      *                         if 2.3 was radians the entry would
  35.      1,2.3                     be 4r2.3
  36.      4d0.3
  37.      +
  38.      /
  39.  
  40.      Most of the usual functions one sees on a scientific calculator
  41.      are also available, e.g.
  42.  
  43.      pi
  44.      4
  45.      /
  46.      sin
  47.  
  48.      would calculate sin(pi/4) or
  49.  
  50.      1r0.5
  51.      sin
  52.  
  53.      would calculate sin(1exp(i0.5)) where 0.5 is the phase angle in
  54.      radians
  55.  
  56.      1,1
  57.      sqrt
  58.  
  59.      evaluates  sqrt(1+i), etc.
  60.  
  61.   Bad things about this program:
  62.     1)  Each operation must be terminated by hitting the <enter> key.
  63.     2)  Computer used to run this program is typically much bigger
  64.         than an HP calculator.
  65.     3)  Memory values may run off top of screen if too many are shown.
  66.         See item 3) in Other Notes: below.
  67.     4)  Help screen is ugly (quite cryptic).  To fix it change the
  68.         code in the function help() if you want to.
  69.     5)  Lot's of other stuff, I'm sure.
  70.  
  71.   Other Notes:
  72.     1)  There is a stack and a bank of memories. The size of each is
  73.         determined by the constants STACKSIZE and MEMSIZE set to 10
  74.         and 100 in the program.  Only STACKDISPLAYSIZE (set to 4)
  75.         stack values are shown.
  76.     2)  The stack and memory are read and stored each time the program
  77.         is run into the file named by the constant INFILE set to
  78.         "c-calc.ini" below.  If INFILE does not exist when beginning
  79.         the program, all stack and memory locations are set to zero.
  80.     3)  The memory locations which contain nonzero entries are not
  81.         shown.  All others are shown. Nonzero is measured by using the
  82.         inline function approxzero().
  83.  
  84.  
  85. *****************************************************************************
  86. *****************************************************************************
  87. *****************************************************************************/
  88.  
  89.  
  90. #include <iostream.h>
  91. #include <stdio.h>
  92. #include <complex.h>
  93. #include <ctype.h> // for toupper()
  94. #include <string.h> // for strcpy()
  95. #include <conio.h> // for getch()
  96.  
  97.  
  98. #define STACKSIZE 10
  99. #define STACKDISPLAYSIZE 4
  100. #define MEMSIZE 100 
  101. #define DEGREE char(248)
  102. #define INIFILE "c-calc.ini"
  103.  
  104. complex j(0,1);
  105. int radian_mode=0; // 0 means degrees mode
  106.  
  107.  
  108.  
  109. inline double deg(double rad) {return (180.0*rad/M_PI);};
  110. inline double rad(double deg) {return (M_PI*deg/180.0);};
  111. inline double mag(complex c) {return(sqrt(norm(c)));};
  112. // suffix d means angle arguement is in degrees rather than radians
  113. inline double argd(complex c) {return(deg(arg(c)));};
  114. inline int approxzero(complex c) {return (mag(c)<1.0e-100);}
  115. inline complex polard(double mag, double deg) { return polar(mag,rad(deg));};
  116.  
  117. inline void showboth(complex c)
  118.   {
  119.      cout << c << " = " << mag(c) << " @ ";
  120.      if (radian_mode) cout << arg(c) << "rad\n";
  121.      else             cout << argd(c) << DEGREE << endl;
  122.   };
  123.  
  124.  
  125. //GLOBAL VARIABLES: c[] stack(RPN-like)     m[] memory
  126. complex c[STACKSIZE];
  127. complex m[MEMSIZE];
  128.  
  129. void showbriefhelp();
  130. void showmemory();
  131. void showstack();
  132. complex GetReal(char *s);
  133. complex GetComplex(char *s);
  134. void Operate(char *s);
  135. void rollup(complex z);
  136. void rolldown();
  137. void help();
  138. void store(char *s);
  139. void retrieve(char *s);
  140. void readini();
  141. void writeini();
  142.  
  143.  
  144. main()
  145. {
  146.   char s[80];
  147.   char ch;
  148.   double x,y;
  149.   readini();
  150.   do
  151.   {
  152.     clrscr();
  153.     showbriefhelp();
  154.     showmemory();
  155.     showstack();
  156.     scanf("%s",s);
  157.     int i=sscanf(s,"%lg %c %lg",&x,&ch,&y);
  158.     switch (i)
  159.     {
  160.       case   3: rollup(GetComplex(s)); break;
  161.       case   1: rollup(GetReal(s)); break;
  162.       default : Operate(s);
  163.     }
  164.  
  165.   } while (strcmpi(s,"q")!=0);
  166.   writeini();
  167.   return 0;
  168.  
  169. }
  170.  
  171.  
  172.  
  173.  
  174. void help()
  175. {
  176.   clrscr();
  177.   cout << "Complex Number Entry:" << endl;
  178.   cout << " 2.1              x-y with y=0" << endl;
  179.   cout << " 2x1 or 2,1       x-y" << endl;
  180.   cout << " 1d45             polar (degrees) 1 @ 45   degrees" << endl;
  181.   cout << " 1r3.14           polar (radians) 1 @ 3.14 radians" << endl;
  182.   cout << " q                to quit" << endl;
  183.   cout << "Other stuff you can enter:     (..) after item gives brief reminder:" << endl;
  184.   cout << " * / + - ^ (x^y) sqr sqrt (careful about branch cut)" << endl;
  185.   cout << " inv cs(change sign) conj pi j i (j,i both sqrt(-1)) e(enter)" << endl;
  186.   cout << " [a]sin [a]cos [a]tan exp ln (log_e) log (log_10) db (20log_10)" << endl;
  187.   cout << " arg[d] (phase angle in radians[degrees])" << endl;
  188.   cout << " rd dr (* or / by 180/pi i.e. rad <--> deg)" << endl;
  189.   cout << " r d  (to rad or deg mode)   swap (re <-->imag)" << endl;
  190.   cout << " xy (x <--> y) cm cstack ca (clear mem or stack or all(both))" << endl;
  191.   cout << " >n <n (memory store retrieve 0<n<" << MEMSIZE << ")" ;
  192.   cout << endl << endl;
  193.   cout << " hit any key to continue .. ";
  194.   getch();
  195. }
  196.  
  197. void showbriefhelp()
  198. {
  199.   cout << "\nh for help             q to quit\n";
  200. }
  201.  
  202.  
  203. void showmemory()
  204. {
  205.   int j=0;
  206.   cout << "MEMORY:" << endl;
  207.   for(int i=0;i<MEMSIZE;i++)
  208.    if (!(approxzero(m[i])))       //ONLY DISPLAY NONZERO MEMORIES
  209.    {
  210.      cout << i << ": " << m[i];
  211.      if (j==0)
  212.      {
  213.        j=1;
  214.        cout << "   ";
  215.      }
  216.      else
  217.      {
  218.        j=0;
  219.        cout << endl;
  220.      }
  221.    }
  222.    if (j==1) cout << endl;
  223.  
  224.  
  225.  
  226. }
  227. void showstack()
  228. {
  229.   cout << "STACK:" << endl;
  230.   for(int i=STACKDISPLAYSIZE-1;i>=0;i--)    showboth(c[i]);
  231. }
  232.  
  233. complex GetReal(char *s)
  234. {
  235.   double x;
  236.   if (sscanf(s,("%lg"),&x)==1) return complex(x,0.0);
  237.   else return complex(0.0,0.0);
  238. }
  239.  
  240. complex GetComplex(char *s)
  241. { double x,y;
  242.   char ch;
  243.   if (sscanf(s,"%lg %c %lg",&x,&ch,&y)==3)
  244.   {
  245.     //cin >> x >> c >> y;
  246.     ch=toupper(ch);
  247.     switch (ch)
  248.     {
  249.       case 'R': return polar(x,y);
  250.       case 'D': return polard(x,y);
  251.       case 'X': return complex(x,y);
  252.       case ',': return complex(x,y);
  253.     }
  254.   }
  255.   return complex(0.0,0.0);
  256.  
  257. }
  258.  
  259.  
  260. void Operate(char *s)
  261. {
  262.   complex temp;
  263.  
  264.   if      (s[0]=='<') {retrieve(s);}
  265.   else if (s[0]=='>') {store(s);}
  266.   else if (strcmpi(s,"d")==0) {radian_mode=0;}
  267.   else if (strcmpi(s,"r")==0) {radian_mode=1;}
  268.   else if (strcmpi(s,"*")==0) {c[0]=c[1]*c[0]; rolldown();}
  269.   else if (strcmpi(s,"/")==0)
  270.           {if(!approxzero(c[0])){c[0]=c[1]/c[0]; rolldown();}}
  271.   else if (strcmpi(s,"+")==0) {c[0]=c[1]+c[0]; rolldown();}
  272.   else if (strcmpi(s,"-")==0) {c[0]=c[1]-c[0]; rolldown();}
  273.   else if (strcmpi(s,"^")==0) {c[0]=pow(c[0],c[1]); rolldown();}
  274.  
  275.   else if (strcmpi(s,"j")==0) {rollup(j);}
  276.   else if (strcmpi(s,"i")==0) {rollup(j);}
  277.   else if (strcmpi(s,"h")==0) {help();}
  278.   else if (strcmpi(s,"?")==0) {help();}
  279.  
  280.   else if (strcmpi(s,"sin")==0) {c[0]=sin(c[0]);}
  281.   else if (strcmpi(s,"cos")==0) {c[0]=cos(c[0]);}
  282.   else if (strcmpi(s,"tan")==0) {c[0]=tan(c[0]);}
  283.  
  284.   else if (strcmpi(s,"asin")==0) {c[0]=asin(c[0]);}
  285.   else if (strcmpi(s,"acos")==0) {c[0]=acos(c[0]);}
  286.   else if (strcmpi(s,"atan")==0) {c[0]=atan(c[0]);}
  287.  
  288.   else if (strcmpi(s,"ln")==0)  {c[0]=log(c[0]);}
  289.   else if (strcmpi(s,"log")==0) {c[0]=log10(c[0]);}
  290.   else if (strcmpi(s,"db")==0)  {c[0]=20*log10(c[0]);}
  291.  
  292.  
  293.  
  294.   else if (strcmpi(s,"exp")==0) {c[0]=exp(c[0]);}
  295.   else if (strcmpi(s,"sqr")==0) {c[0]=c[0]*c[0];}
  296.   else if (strcmpi(s,"sqrt")==0) {c[0]=sqrt(c[0]);}
  297.   else if (strcmpi(s,"inv")==0)
  298.           {if(!approxzero(c[0])) {c[0]=1.0/c[0]; }}
  299.   else if (strcmpi(s,"cs")==0){c[0]= -c[0];}
  300.   else if (strcmpi(s,"pi")==0){rollup(complex(M_PI));}
  301.   else if (strcmpi(s,"swap")==0)
  302.           {c[0]=complex(imag(c[0]),real(c[0]));}
  303.   else if (strcmpi(s,"xy")==0)
  304.           {temp=c[0];c[0]=c[1];c[1]=temp;}
  305.  
  306.   else if (strcmpi(s,"dr")==0)
  307.           {c[0]=complex(rad(real(c[0])),rad(imag(c[0])));}
  308.   else if (strcmpi(s,"rd")==0)
  309.           {c[0]=complex(deg(real(c[0])),deg(imag(c[0])));}
  310.   else if (strcmpi(s,"cm")==0)
  311.           {for(int i=0;i<MEMSIZE;i++) m[i]=complex(0.0,0.0);}
  312.   else if (strcmpi(s,"cstack")==0)
  313.           {for(int i=0;i<STACKSIZE;i++) c[i]=complex(0.0,0.0);}
  314.  
  315.  
  316.   else if (strcmpi(s,"conj")==0)
  317.           {c[0]=conj(c[0]);}
  318.   else if (strcmpi(s,"arg")==0)
  319.           {c[0]=complex(arg(c[0]),0.0);}
  320.   else if (strcmpi(s,"argd")==0)
  321.           {c[0]=complex(argd(c[0]),0.0);}
  322.   else if (strcmpi(s,"e")==0)
  323.           {rollup(c[0]);}
  324.   else if (strcmpi(s,"ca")==0)
  325.           {for(int i=0;i<STACKSIZE;i++) c[i]=complex(0.0,0.0);}
  326.  
  327.   return;
  328.  
  329.  
  330. }
  331.  
  332.  
  333. void rollup(complex z)
  334. {
  335.    for(int i=STACKSIZE-1;i>0;i--) c[i]=c[i-1];
  336.    c[0]=z;
  337. }
  338.  
  339. void rolldown()
  340. {
  341.    for(int i=1;i<STACKSIZE-1;i++) c[i]=c[i+1];
  342.    c[STACKSIZE-1]=complex(0,0);
  343. }
  344.  
  345.  
  346.  
  347. void store(char *s)
  348. {
  349.   int i;
  350.   if (sscanf(s+1,"%d",&i)==1)
  351.   if (i>=0&&i<MEMSIZE) m[i]=c[0];
  352. }
  353.  
  354. void retrieve(char *s)
  355. {
  356.   int i;
  357.   if (sscanf(s+1,"%d",&i)==1)
  358.   if (i>=0&&i<MEMSIZE) rollup(m[i]);
  359. }
  360.  
  361. void readini()
  362. {
  363.   FILE *f;
  364.   int ss,ms;
  365.   double x,y;
  366.   if((f=fopen(INIFILE,"r"))==NULL) return;
  367.   fscanf(f,"%d %d",&ss,&ms);
  368.   for(int i=0;i<ss;i++)
  369.      if(i<STACKSIZE)
  370.      {
  371.        fscanf(f,"%lg %lg",&x,&y);
  372.        c[i]=complex(x,y);
  373.      }
  374.   for(i=0;i<ms;i++)
  375.      if(i<MEMSIZE)
  376.      {
  377.        fscanf(f,"%lg %lg",&x,&y);
  378.        m[i]=complex(x,y);
  379.      }
  380.   fclose(f);
  381.   return;
  382. }
  383.  
  384. void writeini()
  385. {
  386.   FILE *f;
  387.   f=fopen(INIFILE,"w");
  388.   fprintf(f,"%d %d\n",STACKSIZE,MEMSIZE);
  389.   for(int i=0;i<STACKSIZE;i++)
  390.    fprintf(f,"%12.8e %12.8e\n",real(c[i]),imag(c[i]));
  391.   for(i=0;i<MEMSIZE;i++)
  392.    fprintf(f,"%12.8e %12.8e\n",real(m[i]),imag(m[i]));
  393.   fclose(f);
  394.   return;
  395. }
  396.