home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- ************************ C-CALC.CPP ************************************
- ****************************************************************************
- Version 1.0 of C-CALC.CPP by Joe Spector May 3, 1993.
-
- Freeware.
-
- Complex Number Calculator:
-
- CopyJoe policy:
- You can do anything they like with the program or source code
- except sell it or any part of it.
-
- This program has been tested using Borland C++ 3.1
-
- Motivation for c-calc:
- To allow simple evaluation of complex number expressions where
- the complex numbers may be entered in polar or xy notation or
- combinations of the two.
-
- e.g.
-
- to evaluate this
-
- (1.2 + 1.4i)(4*exp(2.3i))
- ---------------------------
- 1 + 2.3j + 4exp(0.3i)
-
-
- the user would type in the following:
-
- 1.2,1.4 <--- , means entered as xy
- 4d2.3 <--- d means polar (in degrees)
- * if 2.3 was radians the entry would
- 1,2.3 be 4r2.3
- 4d0.3
- +
- /
-
- Most of the usual functions one sees on a scientific calculator
- are also available, e.g.
-
- pi
- 4
- /
- sin
-
- would calculate sin(pi/4) or
-
- 1r0.5
- sin
-
- would calculate sin(1exp(i0.5)) where 0.5 is the phase angle in
- radians
-
- 1,1
- sqrt
-
- evaluates sqrt(1+i), etc.
-
- Bad things about this program:
- 1) Each operation must be terminated by hitting the <enter> key.
- 2) Computer used to run this program is typically much bigger
- than an HP calculator.
- 3) Memory values may run off top of screen if too many are shown.
- See item 3) in Other Notes: below.
- 4) Help screen is ugly (quite cryptic). To fix it change the
- code in the function help() if you want to.
- 5) Lot's of other stuff, I'm sure.
-
- Other Notes:
- 1) There is a stack and a bank of memories. The size of each is
- determined by the constants STACKSIZE and MEMSIZE set to 10
- and 100 in the program. Only STACKDISPLAYSIZE (set to 4)
- stack values are shown.
- 2) The stack and memory are read and stored each time the program
- is run into the file named by the constant INFILE set to
- "c-calc.ini" below. If INFILE does not exist when beginning
- the program, all stack and memory locations are set to zero.
- 3) The memory locations which contain nonzero entries are not
- shown. All others are shown. Nonzero is measured by using the
- inline function approxzero().
-
-
- *****************************************************************************
- *****************************************************************************
- *****************************************************************************/
-
-
- #include <iostream.h>
- #include <stdio.h>
- #include <complex.h>
- #include <ctype.h> // for toupper()
- #include <string.h> // for strcpy()
- #include <conio.h> // for getch()
-
-
- #define STACKSIZE 10
- #define STACKDISPLAYSIZE 4
- #define MEMSIZE 100
- #define DEGREE char(248)
- #define INIFILE "c-calc.ini"
-
- complex j(0,1);
- int radian_mode=0; // 0 means degrees mode
-
-
-
- inline double deg(double rad) {return (180.0*rad/M_PI);};
- inline double rad(double deg) {return (M_PI*deg/180.0);};
- inline double mag(complex c) {return(sqrt(norm(c)));};
- // suffix d means angle arguement is in degrees rather than radians
- inline double argd(complex c) {return(deg(arg(c)));};
- inline int approxzero(complex c) {return (mag(c)<1.0e-100);}
- inline complex polard(double mag, double deg) { return polar(mag,rad(deg));};
-
- inline void showboth(complex c)
- {
- cout << c << " = " << mag(c) << " @ ";
- if (radian_mode) cout << arg(c) << "rad\n";
- else cout << argd(c) << DEGREE << endl;
- };
-
-
- //GLOBAL VARIABLES: c[] stack(RPN-like) m[] memory
- complex c[STACKSIZE];
- complex m[MEMSIZE];
-
- void showbriefhelp();
- void showmemory();
- void showstack();
- complex GetReal(char *s);
- complex GetComplex(char *s);
- void Operate(char *s);
- void rollup(complex z);
- void rolldown();
- void help();
- void store(char *s);
- void retrieve(char *s);
- void readini();
- void writeini();
-
-
- main()
- {
- char s[80];
- char ch;
- double x,y;
- readini();
- do
- {
- clrscr();
- showbriefhelp();
- showmemory();
- showstack();
- scanf("%s",s);
- int i=sscanf(s,"%lg %c %lg",&x,&ch,&y);
- switch (i)
- {
- case 3: rollup(GetComplex(s)); break;
- case 1: rollup(GetReal(s)); break;
- default : Operate(s);
- }
-
- } while (strcmpi(s,"q")!=0);
- writeini();
- return 0;
-
- }
-
-
-
-
- void help()
- {
- clrscr();
- cout << "Complex Number Entry:" << endl;
- cout << " 2.1 x-y with y=0" << endl;
- cout << " 2x1 or 2,1 x-y" << endl;
- cout << " 1d45 polar (degrees) 1 @ 45 degrees" << endl;
- cout << " 1r3.14 polar (radians) 1 @ 3.14 radians" << endl;
- cout << " q to quit" << endl;
- cout << "Other stuff you can enter: (..) after item gives brief reminder:" << endl;
- cout << " * / + - ^ (x^y) sqr sqrt (careful about branch cut)" << endl;
- cout << " inv cs(change sign) conj pi j i (j,i both sqrt(-1)) e(enter)" << endl;
- cout << " [a]sin [a]cos [a]tan exp ln (log_e) log (log_10) db (20log_10)" << endl;
- cout << " arg[d] (phase angle in radians[degrees])" << endl;
- cout << " rd dr (* or / by 180/pi i.e. rad <--> deg)" << endl;
- cout << " r d (to rad or deg mode) swap (re <-->imag)" << endl;
- cout << " xy (x <--> y) cm cstack ca (clear mem or stack or all(both))" << endl;
- cout << " >n <n (memory store retrieve 0<n<" << MEMSIZE << ")" ;
- cout << endl << endl;
- cout << " hit any key to continue .. ";
- getch();
- }
-
- void showbriefhelp()
- {
- cout << "\nh for help q to quit\n";
- }
-
-
- void showmemory()
- {
- int j=0;
- cout << "MEMORY:" << endl;
- for(int i=0;i<MEMSIZE;i++)
- if (!(approxzero(m[i]))) //ONLY DISPLAY NONZERO MEMORIES
- {
- cout << i << ": " << m[i];
- if (j==0)
- {
- j=1;
- cout << " ";
- }
- else
- {
- j=0;
- cout << endl;
- }
- }
- if (j==1) cout << endl;
-
-
-
- }
- void showstack()
- {
- cout << "STACK:" << endl;
- for(int i=STACKDISPLAYSIZE-1;i>=0;i--) showboth(c[i]);
- }
-
- complex GetReal(char *s)
- {
- double x;
- if (sscanf(s,("%lg"),&x)==1) return complex(x,0.0);
- else return complex(0.0,0.0);
- }
-
- complex GetComplex(char *s)
- { double x,y;
- char ch;
- if (sscanf(s,"%lg %c %lg",&x,&ch,&y)==3)
- {
- //cin >> x >> c >> y;
- ch=toupper(ch);
- switch (ch)
- {
- case 'R': return polar(x,y);
- case 'D': return polard(x,y);
- case 'X': return complex(x,y);
- case ',': return complex(x,y);
- }
- }
- return complex(0.0,0.0);
-
- }
-
-
- void Operate(char *s)
- {
- complex temp;
-
- if (s[0]=='<') {retrieve(s);}
- else if (s[0]=='>') {store(s);}
- else if (strcmpi(s,"d")==0) {radian_mode=0;}
- else if (strcmpi(s,"r")==0) {radian_mode=1;}
- else if (strcmpi(s,"*")==0) {c[0]=c[1]*c[0]; rolldown();}
- else if (strcmpi(s,"/")==0)
- {if(!approxzero(c[0])){c[0]=c[1]/c[0]; rolldown();}}
- else if (strcmpi(s,"+")==0) {c[0]=c[1]+c[0]; rolldown();}
- else if (strcmpi(s,"-")==0) {c[0]=c[1]-c[0]; rolldown();}
- else if (strcmpi(s,"^")==0) {c[0]=pow(c[0],c[1]); rolldown();}
-
- else if (strcmpi(s,"j")==0) {rollup(j);}
- else if (strcmpi(s,"i")==0) {rollup(j);}
- else if (strcmpi(s,"h")==0) {help();}
- else if (strcmpi(s,"?")==0) {help();}
-
- else if (strcmpi(s,"sin")==0) {c[0]=sin(c[0]);}
- else if (strcmpi(s,"cos")==0) {c[0]=cos(c[0]);}
- else if (strcmpi(s,"tan")==0) {c[0]=tan(c[0]);}
-
- else if (strcmpi(s,"asin")==0) {c[0]=asin(c[0]);}
- else if (strcmpi(s,"acos")==0) {c[0]=acos(c[0]);}
- else if (strcmpi(s,"atan")==0) {c[0]=atan(c[0]);}
-
- else if (strcmpi(s,"ln")==0) {c[0]=log(c[0]);}
- else if (strcmpi(s,"log")==0) {c[0]=log10(c[0]);}
- else if (strcmpi(s,"db")==0) {c[0]=20*log10(c[0]);}
-
-
-
- else if (strcmpi(s,"exp")==0) {c[0]=exp(c[0]);}
- else if (strcmpi(s,"sqr")==0) {c[0]=c[0]*c[0];}
- else if (strcmpi(s,"sqrt")==0) {c[0]=sqrt(c[0]);}
- else if (strcmpi(s,"inv")==0)
- {if(!approxzero(c[0])) {c[0]=1.0/c[0]; }}
- else if (strcmpi(s,"cs")==0){c[0]= -c[0];}
- else if (strcmpi(s,"pi")==0){rollup(complex(M_PI));}
- else if (strcmpi(s,"swap")==0)
- {c[0]=complex(imag(c[0]),real(c[0]));}
- else if (strcmpi(s,"xy")==0)
- {temp=c[0];c[0]=c[1];c[1]=temp;}
-
- else if (strcmpi(s,"dr")==0)
- {c[0]=complex(rad(real(c[0])),rad(imag(c[0])));}
- else if (strcmpi(s,"rd")==0)
- {c[0]=complex(deg(real(c[0])),deg(imag(c[0])));}
- else if (strcmpi(s,"cm")==0)
- {for(int i=0;i<MEMSIZE;i++) m[i]=complex(0.0,0.0);}
- else if (strcmpi(s,"cstack")==0)
- {for(int i=0;i<STACKSIZE;i++) c[i]=complex(0.0,0.0);}
-
-
- else if (strcmpi(s,"conj")==0)
- {c[0]=conj(c[0]);}
- else if (strcmpi(s,"arg")==0)
- {c[0]=complex(arg(c[0]),0.0);}
- else if (strcmpi(s,"argd")==0)
- {c[0]=complex(argd(c[0]),0.0);}
- else if (strcmpi(s,"e")==0)
- {rollup(c[0]);}
- else if (strcmpi(s,"ca")==0)
- {for(int i=0;i<STACKSIZE;i++) c[i]=complex(0.0,0.0);}
-
- return;
-
-
- }
-
-
- void rollup(complex z)
- {
- for(int i=STACKSIZE-1;i>0;i--) c[i]=c[i-1];
- c[0]=z;
- }
-
- void rolldown()
- {
- for(int i=1;i<STACKSIZE-1;i++) c[i]=c[i+1];
- c[STACKSIZE-1]=complex(0,0);
- }
-
-
-
- void store(char *s)
- {
- int i;
- if (sscanf(s+1,"%d",&i)==1)
- if (i>=0&&i<MEMSIZE) m[i]=c[0];
- }
-
- void retrieve(char *s)
- {
- int i;
- if (sscanf(s+1,"%d",&i)==1)
- if (i>=0&&i<MEMSIZE) rollup(m[i]);
- }
-
- void readini()
- {
- FILE *f;
- int ss,ms;
- double x,y;
- if((f=fopen(INIFILE,"r"))==NULL) return;
- fscanf(f,"%d %d",&ss,&ms);
- for(int i=0;i<ss;i++)
- if(i<STACKSIZE)
- {
- fscanf(f,"%lg %lg",&x,&y);
- c[i]=complex(x,y);
- }
- for(i=0;i<ms;i++)
- if(i<MEMSIZE)
- {
- fscanf(f,"%lg %lg",&x,&y);
- m[i]=complex(x,y);
- }
- fclose(f);
- return;
- }
-
- void writeini()
- {
- FILE *f;
- f=fopen(INIFILE,"w");
- fprintf(f,"%d %d\n",STACKSIZE,MEMSIZE);
- for(int i=0;i<STACKSIZE;i++)
- fprintf(f,"%12.8e %12.8e\n",real(c[i]),imag(c[i]));
- for(i=0;i<MEMSIZE;i++)
- fprintf(f,"%12.8e %12.8e\n",real(m[i]),imag(m[i]));
- fclose(f);
- return;
- }
-