math.c revision 8512f934
14d9b34d9Smrg/* $XConsortium: math.c,v 1.17 91/07/25 17:51:34 rws Exp $
24d9b34d9Smrg * $MIT: contrib/programs/xcalc/math.c,v 3.2 1999/12/14 18:53:00 gjcoram Exp$
34d9b34d9Smrg * $XFree86: xc/programs/xcalc/math.c,v 1.5tsi Exp $
44d9b34d9Smrg * $XdotOrg: xc/programs/xcalc/math.c,v 1.3 2004/05/23 20:03:49 alanc Exp $
54d9b34d9Smrg *
64d9b34d9Smrg *  math.c  -  mathematics functions for a hand calculator under X
74d9b34d9Smrg *
84d9b34d9Smrg *  Author:    John H. Bradley, University of Pennsylvania
94d9b34d9Smrg *                (bradley@cis.upenn.edu)
104d9b34d9Smrg *                     March, 1987
114d9b34d9Smrg *
124d9b34d9Smrg *  RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena
134d9b34d9Smrg *
144d9b34d9Smrg *  Modified to be a client of the Xt toolkit and the Athena widget set by
154d9b34d9Smrg *  Donna Converse, MIT X Consortium.  This is all that remains of the
164d9b34d9Smrg *  original calculator, and it still needs to be rewritten.  The HP
174d9b34d9Smrg *  functionality should be separated from the TI functionality.
184d9b34d9Smrg *  Beware the HP functions: there are still errors here.
194d9b34d9Smrg *
204d9b34d9Smrg *  Geoffrey Coram fixed most of the HP mode bugs.
214d9b34d9Smrg */
224d9b34d9Smrg
234d9b34d9Smrg#include "xcalc.h"
244d9b34d9Smrg
254d9b34d9Smrg#ifdef _CRAY		/* kludge around Cray STDC compiler */
264d9b34d9Smrgdouble (*log_p)() = log;
274d9b34d9Smrg#define log ((*log_p))
284d9b34d9Smrgdouble (*exp_p)() = exp;
294d9b34d9Smrg#define exp ((*exp_p))
304d9b34d9Smrgdouble (*sqrt_p)() = sqrt;
314d9b34d9Smrg#define sqrt ((*sqrt_p))
324d9b34d9Smrgdouble (*log10_p)() = log10;
334d9b34d9Smrg#define log10 ((*log10_p))
344d9b34d9Smrgdouble (*atan2_p)() = atan2;
354d9b34d9Smrg#define atan2 ((*atan2_p))
364d9b34d9Smrgdouble (*asin_p)() = asin;
374d9b34d9Smrg#define asin ((*asin_p))
384d9b34d9Smrgdouble (*acos_p)() = acos;
394d9b34d9Smrg#define acos ((*acos_p))
404d9b34d9Smrgdouble (*atan_p)() = atan;
414d9b34d9Smrg#define atan ((*atan_p))
424d9b34d9Smrgdouble (*sin_p)() = sin;
434d9b34d9Smrg#define sin ((*sin_p))
444d9b34d9Smrgdouble (*cos_p)() = cos;
454d9b34d9Smrg#define cos ((*cos_p))
464d9b34d9Smrgdouble (*tan_p)() = tan;
474d9b34d9Smrg#define tan ((*tan_p))
484d9b34d9Smrgdouble (*pow_p)() = pow;
494d9b34d9Smrg#define pow ((*pow_p))
504d9b34d9Smrg#endif /* _CRAY */
514d9b34d9Smrg
524d9b34d9Smrg#ifndef PI		/* sometimes defined in math.h */
534d9b34d9Smrg#define PI          3.14159265358979
544d9b34d9Smrg#endif
554d9b34d9Smrg#define E           2.71828182845904
564d9b34d9Smrg#define MAXDISP     11
574d9b34d9Smrg#define DEG 0		/* DRG mode.  used for trig calculations */
584d9b34d9Smrg#define RAD 1
594d9b34d9Smrg#define GRAD 2
604d9b34d9Smrg#define min(a,b) ((a) < (b) ? (a) : (b))
614d9b34d9Smrg#define max(a,b) ((a) > (b) ? (a) : (b))
624d9b34d9Smrg#define True	1
634d9b34d9Smrg#define False   0
644d9b34d9Smrg
654d9b34d9Smrg#ifndef IEEE
668512f934Smrgjmp_buf env;
674d9b34d9Smrg#endif
684d9b34d9Smrg
694d9b34d9Smrg
704d9b34d9Smrg/* This section is all of the state machine that implements the calculator
714d9b34d9Smrg * functions.  Much of it is shared between the infix and rpn modes.
724d9b34d9Smrg */
734d9b34d9Smrg
748512f934Smrgstatic int flagINV, flagPAREN, flagM, drgmode;	/* display flags */
754d9b34d9Smrg
764d9b34d9Smrgstatic double drg2rad=PI/180.0;  /* Conversion factors for trig funcs */
774d9b34d9Smrgstatic double rad2drg=180.0/PI;
784d9b34d9Smrgstatic int entered=1;  /* true if display contains a valid number.
794d9b34d9Smrg                          if==2, then use 'dnum', rather than the string
804d9b34d9Smrg                          stored in the display.  (for accuracy)
814d9b34d9Smrg                          if==3, then error occurred, only CLR & AC work */
824d9b34d9Smrg/* entered seems to be overloaded - dmc */
834d9b34d9Smrgstatic int lift_enabled = 0;	/* for rpn mode only */
844d9b34d9Smrg
854d9b34d9Smrgstatic int CLR    =0;  /* CLR clears display.  if 1, clears acc, also */
864d9b34d9Smrgstatic int Dpoint=0;  /* to prevent using decimal pt twice in a # */
874d9b34d9Smrgstatic int clrdisp=1;  /* if true clears display before entering # */
884d9b34d9Smrgstatic int lastop =kCLR;
894d9b34d9Smrgstatic int memop  =kCLR;
904d9b34d9Smrgstatic int exponent=0;
914d9b34d9Smrgstatic double acc =0.0;
924d9b34d9Smrgstatic double dnum=0.0;
934d9b34d9Smrg#define XCALC_MEMORY 10
944d9b34d9Smrgstatic double mem[XCALC_MEMORY] = { 0.0 };
954d9b34d9Smrg
964d9b34d9Smrgstatic void   DrawDisplay(void);
974d9b34d9Smrgstatic void   PushOp(int op);
984d9b34d9Smrgstatic int    PopOp(void);
994d9b34d9Smrgstatic int    isopempty(void);
1004d9b34d9Smrg#ifdef DEBUG
1014d9b34d9Smrgstatic void   showstack(char *string);
1024d9b34d9Smrg#endif
1034d9b34d9Smrgstatic void   PushNum(double num);
1044d9b34d9Smrgstatic double PopNum(void);
1054d9b34d9Smrgstatic void   RollNum(int dir);
1064d9b34d9Smrgstatic void   ClearStacks(void);
1074d9b34d9Smrgstatic int    priority(int op);
1084d9b34d9Smrg
1094d9b34d9Smrg/*
1104d9b34d9Smrg * The following is to deal with the unfortunate assumption that if errno
1114d9b34d9Smrg * is non-zero then an error has occurred.  On some systems (e.g. Ultrix),
1124d9b34d9Smrg * sscanf will call lower level routines that will set errno.
1134d9b34d9Smrg */
1144d9b34d9Smrg
1154d9b34d9Smrgstatic void
1168512f934Smrgparse_double (char *src, char *fmt, double *dp)
1174d9b34d9Smrg{
1184d9b34d9Smrg    int olderrno = errno;
1194d9b34d9Smrg
1204d9b34d9Smrg    (void) sscanf (src, fmt, dp);
1214d9b34d9Smrg    errno = olderrno;
1224d9b34d9Smrg    return;
1234d9b34d9Smrg}
1244d9b34d9Smrg
1254d9b34d9Smrg
1264d9b34d9Smrg/*********************************/
1278512f934Smrgint pre_op(int keynum)
1284d9b34d9Smrg{
1294d9b34d9Smrg    if (keynum==-1) return(0);
1304d9b34d9Smrg
1314d9b34d9Smrg    errno = 0;			/* for non-IEEE machines */
1324d9b34d9Smrg
1334d9b34d9Smrg    if ( (entered==3) && !(keynum==kCLR || keynum==kOFF)) {
1344d9b34d9Smrg      if (rpn) {
1354d9b34d9Smrg	clrdisp++;
1364d9b34d9Smrg      } else {
1374d9b34d9Smrg        ringbell();
1384d9b34d9Smrg        return(1);	/* the intent was probably not to do the operation */
1394d9b34d9Smrg      }
1404d9b34d9Smrg    }
1414d9b34d9Smrg
1424d9b34d9Smrg    if (keynum != kCLR) CLR=0;
1434d9b34d9Smrg    return(0);
1444d9b34d9Smrg}
1454d9b34d9Smrg
1464d9b34d9Smrg#ifndef IEEE
1474d9b34d9Smrg
1484d9b34d9Smrg/* cannot assign result of setjmp under ANSI C, use global instead */
1494d9b34d9Smrgstatic volatile int SignalKind;
1504d9b34d9Smrg
1518512f934Smrgvoid fail_op(void)
1524d9b34d9Smrg{
1534d9b34d9Smrg    if (SignalKind == SIGFPE)
1548512f934Smrg	strcpy(dispstr, "math error");
1558512f934Smrg    else if (SignalKind == SIGILL)
1568512f934Smrg	strcpy(dispstr, "illegal operand");
1574d9b34d9Smrg
1584d9b34d9Smrg    entered=3;
1594d9b34d9Smrg    DrawDisplay();
1604d9b34d9Smrg    return;
1614d9b34d9Smrg}
1624d9b34d9Smrg
1634d9b34d9Smrg/*ARGSUSED*/
1648512f934Smrgsignal_t fperr(int sig)
1654d9b34d9Smrg{
1664d9b34d9Smrg#if defined(SYSV) || defined(SVR4) || defined(linux)
1678512f934Smrg    signal(SIGFPE, fperr);
1684d9b34d9Smrg#endif
1694d9b34d9Smrg    SignalKind = sig;
1704d9b34d9Smrg    longjmp(env,1);
1714d9b34d9Smrg}
1724d9b34d9Smrg
1734d9b34d9Smrg/* for VAX BSD4.3 */
1744d9b34d9Smrg/*ARGSUSED*/
1758512f934Smrgsignal_t illerr(int sig)
1764d9b34d9Smrg{
1774d9b34d9Smrg    /* not reset when caught? */
1788512f934Smrg    signal(SIGILL, illerr);
1794d9b34d9Smrg
1804d9b34d9Smrg    SignalKind = sig;
1814d9b34d9Smrg    longjmp(env,1);
1824d9b34d9Smrg}
1834d9b34d9Smrg
1844d9b34d9Smrg#endif	/* not IEEE */
1854d9b34d9Smrg
1864d9b34d9Smrg
1878512f934Smrgvoid post_op(void)
1884d9b34d9Smrg{
1894d9b34d9Smrg#ifdef DEBUG
1904d9b34d9Smrg    showstack("\0");
1914d9b34d9Smrg#endif
1924d9b34d9Smrg#ifndef IEEE
1934d9b34d9Smrg    if (errno) {
1944d9b34d9Smrg        strcpy(dispstr,"error");
1954d9b34d9Smrg        DrawDisplay();
1964d9b34d9Smrg        entered=3;
1974d9b34d9Smrg        errno=0;
1984d9b34d9Smrg        }
1994d9b34d9Smrg#endif
2004d9b34d9Smrg}
2014d9b34d9Smrg/*-------------------------------------------------------------------------*/
2024d9b34d9Smrgstatic void
2034d9b34d9SmrgDrawDisplay(void)
2044d9b34d9Smrg{
2054d9b34d9Smrg    if ((int) strlen(dispstr) > 12) {	 /* strip out some decimal digits */
2064d9b34d9Smrg        char tmp[32];
2074d9b34d9Smrg        char *estr = index(dispstr,'e');  /* search for exponent part */
2084d9b34d9Smrg        if (!estr) dispstr[12]='\0';      /* no exp, just trunc. */
2094d9b34d9Smrg        else {
2104d9b34d9Smrg            if ((int) strlen(estr) <= 4)
2114d9b34d9Smrg                sprintf(tmp,"%.8s",dispstr); /* leftmost 8 chars */
2124d9b34d9Smrg            else
2134d9b34d9Smrg                sprintf(tmp,"%.7s",dispstr); /* leftmost 7 chars */
2144d9b34d9Smrg            strcat (tmp,estr);            /* plus exponent */
2154d9b34d9Smrg            strcpy (dispstr,tmp);
2164d9b34d9Smrg            }
2174d9b34d9Smrg        }
2184d9b34d9Smrg    draw(dispstr);
2194d9b34d9Smrg    setflag(XCalc_MEMORY, (flagM));
2204d9b34d9Smrg    setflag(XCalc_INVERSE, (flagINV));
2214d9b34d9Smrg    setflag(XCalc_DEGREE, (drgmode==DEG));
2224d9b34d9Smrg    setflag(XCalc_RADIAN, (drgmode==RAD));
2234d9b34d9Smrg    setflag(XCalc_GRADAM, (drgmode==GRAD));
2244d9b34d9Smrg    setflag(XCalc_PAREN, (flagPAREN));
2254d9b34d9Smrg}
2264d9b34d9Smrg
2274d9b34d9Smrg/*-------------------------------------------------------------------------*/
2284d9b34d9Smrgvoid
2298512f934Smrgnumeric(int keynum)
2304d9b34d9Smrg{
2314d9b34d9Smrg    char	st[2];
2324d9b34d9Smrg    int		cell = 0;
2334d9b34d9Smrg
2344d9b34d9Smrg  flagINV=0;
2354d9b34d9Smrg
2364d9b34d9Smrg  if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) {
2374d9b34d9Smrg      switch (keynum) {
2384d9b34d9Smrg	case kONE:	cell = 1; break;
2394d9b34d9Smrg	case kTWO:	cell = 2; break;
2404d9b34d9Smrg	case kTHREE:	cell = 3; break;
2414d9b34d9Smrg	case kFOUR:	cell = 4; break;
2424d9b34d9Smrg	case kFIVE:	cell = 5; break;
2434d9b34d9Smrg	case kSIX:	cell = 6; break;
2444d9b34d9Smrg	case kSEVEN:	cell = 7; break;
2454d9b34d9Smrg	case kEIGHT:	cell = 8; break;
2464d9b34d9Smrg	case kNINE:	cell = 9; break;
2474d9b34d9Smrg	case kZERO:	cell = 0; break;
2484d9b34d9Smrg      }
2494d9b34d9Smrg      switch (memop) {
2504d9b34d9Smrg      case kSTO:
2514d9b34d9Smrg	mem[cell] = dnum;
2524d9b34d9Smrg	lift_enabled = 1;
2534d9b34d9Smrg	entered = 2;
2544d9b34d9Smrg	clrdisp++;
2554d9b34d9Smrg	break;
2564d9b34d9Smrg      case kRCL:
2574d9b34d9Smrg	PushNum(dnum);
2584d9b34d9Smrg	dnum = mem[cell];
2594d9b34d9Smrg	sprintf(dispstr, "%.8g", dnum);
2604d9b34d9Smrg	lift_enabled = 1;
2614d9b34d9Smrg        entered = 1;
2624d9b34d9Smrg	clrdisp++;
2634d9b34d9Smrg	break;
2644d9b34d9Smrg      case kSUM:
2654d9b34d9Smrg	mem[cell] += dnum;
2664d9b34d9Smrg	lift_enabled = 1;
2674d9b34d9Smrg	entered = 2;
2684d9b34d9Smrg	clrdisp++;
2694d9b34d9Smrg	break;
2704d9b34d9Smrg      }
2714d9b34d9Smrg      memop = kCLR;
2724d9b34d9Smrg      DrawDisplay();
2734d9b34d9Smrg      return;
2744d9b34d9Smrg  }
2754d9b34d9Smrg
2764d9b34d9Smrg  if (clrdisp) {
2774d9b34d9Smrg    dispstr[0]='\0';
2784d9b34d9Smrg    exponent=Dpoint=0;
2794d9b34d9Smrg/*    if (rpn && entered==2)
2804d9b34d9Smrg      PushNum(dnum);
2814d9b34d9Smrg */
2824d9b34d9Smrg    if (rpn & lift_enabled)
2834d9b34d9Smrg	PushNum(dnum);
2844d9b34d9Smrg  }
2854d9b34d9Smrg  if ((int) strlen(dispstr) >= MAXDISP)
2864d9b34d9Smrg    return;
2874d9b34d9Smrg
2884d9b34d9Smrg    switch (keynum){
2894d9b34d9Smrg      case kONE:	st[0] = '1'; break;
2904d9b34d9Smrg      case kTWO:	st[0] = '2'; break;
2914d9b34d9Smrg      case kTHREE:	st[0] = '3'; break;
2924d9b34d9Smrg      case kFOUR:	st[0] = '4'; break;
2934d9b34d9Smrg      case kFIVE:	st[0] = '5'; break;
2944d9b34d9Smrg      case kSIX:	st[0] = '6'; break;
2954d9b34d9Smrg      case kSEVEN:	st[0] = '7'; break;
2964d9b34d9Smrg      case kEIGHT:	st[0] = '8'; break;
2974d9b34d9Smrg      case kNINE:	st[0] = '9'; break;
2984d9b34d9Smrg      case kZERO:	st[0] = '0'; break;
2994d9b34d9Smrg    }
3004d9b34d9Smrg    st[1] = '\0';
3014d9b34d9Smrg    strcat(dispstr,st);
3024d9b34d9Smrg
3034d9b34d9Smrg  DrawDisplay();
3044d9b34d9Smrg  if (clrdisp && keynum != kZERO)
3054d9b34d9Smrg    clrdisp=0; /*no leading 0s*/
3064d9b34d9Smrg  memop = keynum;
3074d9b34d9Smrg  entered=1;
3084d9b34d9Smrg  lift_enabled = 0;
3094d9b34d9Smrg}
3104d9b34d9Smrg
3114d9b34d9Smrgvoid
3124d9b34d9Smrgbkspf(void)
3134d9b34d9Smrg{
3144d9b34d9Smrg
3154d9b34d9Smrg  lift_enabled = 0;
3164d9b34d9Smrg
3174d9b34d9Smrg  if (! flagINV)
3184d9b34d9Smrg  {
3194d9b34d9Smrg      if (entered!=1) {
3204d9b34d9Smrg	  clearf();
3214d9b34d9Smrg	  return;
3224d9b34d9Smrg      }
3234d9b34d9Smrg      if (clrdisp)
3244d9b34d9Smrg	  return;
3254d9b34d9Smrg      if ((int) strlen(dispstr) > 0) {
3264d9b34d9Smrg#ifndef X_LOCALE
3274d9b34d9Smrg          const char *dp = localeconv()->decimal_point;
3284d9b34d9Smrg          size_t dp_len = strlen(dp);
3294d9b34d9Smrg          size_t ds_len = strlen(dispstr);
3304d9b34d9Smrg          if (ds_len >= dp_len && strcmp(dispstr + ds_len - dp_len, dp) == 0)
3314d9b34d9Smrg             Dpoint=0;
3324d9b34d9Smrg#else
3334d9b34d9Smrg	  if (dispstr[strlen(dispstr)-1] == '.')
3344d9b34d9Smrg             Dpoint=0;
3354d9b34d9Smrg#endif
3364d9b34d9Smrg	  dispstr[strlen(dispstr)-1] = 0;
3374d9b34d9Smrg      }
3384d9b34d9Smrg      if (strlen(dispstr) == 0) {
3394d9b34d9Smrg	  strcat(dispstr, "0");
3404d9b34d9Smrg	  clrdisp++;
3414d9b34d9Smrg      }
3424d9b34d9Smrg  }
3434d9b34d9Smrg  else
3444d9b34d9Smrg  {
3454d9b34d9Smrg      strcpy(dispstr, "0");
3464d9b34d9Smrg      dnum = 0.0;
3474d9b34d9Smrg      clrdisp++;
3484d9b34d9Smrg      flagINV = 0;
3494d9b34d9Smrg  }
3504d9b34d9Smrg  DrawDisplay();
3514d9b34d9Smrg}
3524d9b34d9Smrg
3534d9b34d9Smrgvoid
3544d9b34d9Smrgdecf(void)
3554d9b34d9Smrg{
3564d9b34d9Smrg  flagINV=0;
3574d9b34d9Smrg  if (clrdisp) {
3584d9b34d9Smrg      if (rpn && lift_enabled)
3594d9b34d9Smrg	PushNum(dnum);
3604d9b34d9Smrg      strcpy(dispstr,"0");
3614d9b34d9Smrg  }
3624d9b34d9Smrg  if (!Dpoint) {
3634d9b34d9Smrg#ifndef X_LOCALE
3644d9b34d9Smrg    strcat(dispstr, localeconv()->decimal_point);
3654d9b34d9Smrg#else
3664d9b34d9Smrg    strcat(dispstr, ".");
3674d9b34d9Smrg#endif
3684d9b34d9Smrg    DrawDisplay();
3694d9b34d9Smrg    Dpoint++;
3704d9b34d9Smrg  }
3714d9b34d9Smrg  clrdisp=0;
3724d9b34d9Smrg  entered=1;
3734d9b34d9Smrg}
3744d9b34d9Smrg
3754d9b34d9Smrgvoid
3764d9b34d9Smrgeef(void)
3774d9b34d9Smrg{
3784d9b34d9Smrg  flagINV=0;
3794d9b34d9Smrg  if (clrdisp) {
3804d9b34d9Smrg      if (rpn && lift_enabled)
3814d9b34d9Smrg	PushNum(dnum);
3824d9b34d9Smrg      strcpy(dispstr, rpn ? "1" : "0");
3834d9b34d9Smrg  }
3844d9b34d9Smrg  if (!exponent) {
3854d9b34d9Smrg    strcat(dispstr,"E+");
3864d9b34d9Smrg    DrawDisplay();
3874d9b34d9Smrg    exponent=strlen(dispstr)-1;  /* where the '-' goes */
3884d9b34d9Smrg  }
3894d9b34d9Smrg  clrdisp=0;
3904d9b34d9Smrg  entered=1;
3914d9b34d9Smrg}
3924d9b34d9Smrg
3934d9b34d9Smrgvoid
3944d9b34d9Smrgclearf(void)
3954d9b34d9Smrg{
3964d9b34d9Smrg  flagINV=0;
3974d9b34d9Smrg  if (CLR && !rpn) { /* clear all */
3984d9b34d9Smrg    ClearStacks();
3994d9b34d9Smrg    flagPAREN=0;
4004d9b34d9Smrg  }
4014d9b34d9Smrg  CLR++;
4024d9b34d9Smrg  exponent=Dpoint=0;
4034d9b34d9Smrg  clrdisp=1;
4044d9b34d9Smrg  entered=1;
4054d9b34d9Smrg  strcpy(dispstr,"0");
4064d9b34d9Smrg  DrawDisplay();
4074d9b34d9Smrg}
4084d9b34d9Smrg
4094d9b34d9Smrgvoid
4104d9b34d9Smrgnegf(void)
4114d9b34d9Smrg{
4124d9b34d9Smrg  flagINV=0;
4134d9b34d9Smrg  if (exponent) {       /* neg the exponent */
4144d9b34d9Smrg    if (dispstr[exponent]=='-')
4154d9b34d9Smrg      dispstr[exponent]='+';
4164d9b34d9Smrg    else
4174d9b34d9Smrg      dispstr[exponent]='-';
4184d9b34d9Smrg    DrawDisplay();
4194d9b34d9Smrg    return;
4204d9b34d9Smrg  }
4214d9b34d9Smrg
4224d9b34d9Smrg  if (strcmp("0",dispstr)==0)
4234d9b34d9Smrg    return;			/* don't neg a zero */
4244d9b34d9Smrg  if (dispstr[0]=='-')	 	/* already neg-ed */
4254d9b34d9Smrg    strcpy(dispstr,dispstr+1);  /* move str left once */
4264d9b34d9Smrg  else {			/* not neg-ed.  add a '-' */
4274d9b34d9Smrg    char tmp[32];
4284d9b34d9Smrg    sprintf(tmp,"-%s",dispstr);
4294d9b34d9Smrg    strcpy(dispstr,tmp);
4304d9b34d9Smrg  }
4314d9b34d9Smrg  if (entered==2)
4324d9b34d9Smrg    dnum = -1.0 * dnum;
4334d9b34d9Smrg  DrawDisplay();
4344d9b34d9Smrg}
4354d9b34d9Smrg
4364d9b34d9Smrg/* Two operand functions for infix calc */
4374d9b34d9Smrgvoid
4384d9b34d9Smrgtwoop(int keynum)
4394d9b34d9Smrg{
4404d9b34d9Smrg  if (flagINV) {
4414d9b34d9Smrg    flagINV=0;
4424d9b34d9Smrg    DrawDisplay();
4434d9b34d9Smrg  }
4444d9b34d9Smrg
4454d9b34d9Smrg  if (!entered) {		/* something like "5+*" */
4464d9b34d9Smrg    if (!isopempty())
4474d9b34d9Smrg      (void) PopOp();			/* replace the prev op */
4484d9b34d9Smrg    PushOp(keynum);		/* with the new one */
4494d9b34d9Smrg    return;
4504d9b34d9Smrg  }
4514d9b34d9Smrg
4524d9b34d9Smrg  if (entered==1)
4534d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
4544d9b34d9Smrg
4554d9b34d9Smrg  clrdisp=CLR=1;
4564d9b34d9Smrg  entered=Dpoint=exponent=0;
4574d9b34d9Smrg
4584d9b34d9Smrg  if (!isopempty()) {  /* there was a previous op */
4594d9b34d9Smrg    lastop=PopOp();   /* get it */
4604d9b34d9Smrg
4614d9b34d9Smrg    if (lastop==kLPAR) {  /* put it back */
4624d9b34d9Smrg      PushOp(kLPAR);
4634d9b34d9Smrg      PushOp(keynum);
4644d9b34d9Smrg      PushNum(dnum);
4654d9b34d9Smrg      return;
4664d9b34d9Smrg    }
4674d9b34d9Smrg
4684d9b34d9Smrg    /* now, if the current op (keynum) is of
4694d9b34d9Smrg       higher priority than the lastop, the current
4704d9b34d9Smrg       op and number are just pushed on top
4714d9b34d9Smrg       Priorities:  (Y^X) > *,/ > +,- */
4724d9b34d9Smrg
4734d9b34d9Smrg    if (priority(keynum) > priority(lastop)) {
4744d9b34d9Smrg      PushNum(dnum);
4754d9b34d9Smrg      PushOp(lastop);
4764d9b34d9Smrg      PushOp(keynum);
4774d9b34d9Smrg    } else {  /* execute lastop on lastnum and dnum, push
4784d9b34d9Smrg	       result and current op on stack */
4794d9b34d9Smrg      acc=PopNum();
4804d9b34d9Smrg      switch (lastop) { /* perform the operation */
4814d9b34d9Smrg      case kADD: acc += dnum;  break;
4824d9b34d9Smrg      case kSUB: acc -= dnum;  break;
4834d9b34d9Smrg      case kMUL: acc *= dnum;  break;
4844d9b34d9Smrg      case kDIV: acc /= dnum;  break;
4854d9b34d9Smrg      case kPOW: acc =  pow(acc,dnum);  break;
4864d9b34d9Smrg	}
4874d9b34d9Smrg      PushNum(acc);
4884d9b34d9Smrg      PushOp(keynum);
4894d9b34d9Smrg      sprintf(dispstr,"%.8g",acc);
4904d9b34d9Smrg      DrawDisplay();
4914d9b34d9Smrg      dnum=acc;
4924d9b34d9Smrg    }
4934d9b34d9Smrg  }
4944d9b34d9Smrg  else { /* op stack is empty, push op and num */
4954d9b34d9Smrg    PushOp(keynum);
4964d9b34d9Smrg    PushNum(dnum);
4974d9b34d9Smrg  }
4984d9b34d9Smrg}
4994d9b34d9Smrg
5004d9b34d9Smrg/* Two operand functions for rpn calc */
5014d9b34d9Smrgvoid
5024d9b34d9Smrgtwof(int keynum)
5034d9b34d9Smrg{
5044d9b34d9Smrg  if (flagINV) {
5054d9b34d9Smrg    flagINV=0;
5064d9b34d9Smrg    DrawDisplay();
5074d9b34d9Smrg  }
5084d9b34d9Smrg  if (!entered)
5094d9b34d9Smrg    return;
5104d9b34d9Smrg  if (entered==1)
5114d9b34d9Smrg    parse_double(dispstr, "%lf", &dnum);
5124d9b34d9Smrg  acc = PopNum();
5134d9b34d9Smrg  switch(keynum) {
5144d9b34d9Smrg  case kADD: acc += dnum;  break;
5154d9b34d9Smrg  case kSUB: acc -= dnum;  break;
5164d9b34d9Smrg  case kMUL: acc *= dnum;  break;
5174d9b34d9Smrg  case kDIV: acc /= dnum;  break;
5184d9b34d9Smrg  case kPOW: acc =  pow(acc,dnum);  break;
5194d9b34d9Smrg  case kXXY: PushNum(dnum);
5204d9b34d9Smrg  }
5214d9b34d9Smrg  sprintf(dispstr, "%.8g", acc);
5224d9b34d9Smrg  DrawDisplay();
5234d9b34d9Smrg  clrdisp++;
5244d9b34d9Smrg  Dpoint = exponent = 0;
5254d9b34d9Smrg  entered = 2;
5264d9b34d9Smrg  lift_enabled = 1;
5274d9b34d9Smrg  dnum = acc;
5284d9b34d9Smrg}
5294d9b34d9Smrg
5304d9b34d9Smrgvoid
5314d9b34d9Smrgentrf(void)
5324d9b34d9Smrg{
5334d9b34d9Smrg  flagINV=0;
5344d9b34d9Smrg  if (!entered)
5354d9b34d9Smrg    return;
5364d9b34d9Smrg
5374d9b34d9Smrg  clrdisp=CLR=1;
5384d9b34d9Smrg  Dpoint=exponent=0;
5394d9b34d9Smrg
5404d9b34d9Smrg  if (entered==1)
5414d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
5424d9b34d9Smrg  entered=2;
5434d9b34d9Smrg  memop = kENTR;
5444d9b34d9Smrg  PushNum(dnum);
5454d9b34d9Smrg  lift_enabled = 0;
5464d9b34d9Smrg}
5474d9b34d9Smrg
5484d9b34d9Smrgvoid
5494d9b34d9Smrgequf(void)
5504d9b34d9Smrg{
5514d9b34d9Smrg  flagINV=0;
5524d9b34d9Smrg  if (!entered)
5534d9b34d9Smrg    return;
5544d9b34d9Smrg
5554d9b34d9Smrg  clrdisp=CLR=1;
5564d9b34d9Smrg  Dpoint=exponent=0;
5574d9b34d9Smrg
5584d9b34d9Smrg  if (entered==1)
5594d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
5604d9b34d9Smrg  entered=2;
5614d9b34d9Smrg
5624d9b34d9Smrg  PushNum(dnum);
5634d9b34d9Smrg
5644d9b34d9Smrg  while (!isopempty()) {  /* do all pending ops */
5654d9b34d9Smrg    dnum=PopNum();
5664d9b34d9Smrg    acc=PopNum();
5674d9b34d9Smrg    lastop=PopOp();
5684d9b34d9Smrg    switch (lastop) {
5694d9b34d9Smrg    case kADD:  acc += dnum;
5704d9b34d9Smrg		break;
5714d9b34d9Smrg    case kSUB:  acc -= dnum;
5724d9b34d9Smrg		break;
5734d9b34d9Smrg    case kMUL:  acc *= dnum;
5744d9b34d9Smrg		break;
5754d9b34d9Smrg    case kDIV:  acc /= dnum;
5764d9b34d9Smrg		break;
5774d9b34d9Smrg    case kPOW:  acc = pow(acc,dnum);
5784d9b34d9Smrg		break;
5794d9b34d9Smrg    case kLPAR:	flagPAREN--;
5804d9b34d9Smrg		PushNum(acc);
5814d9b34d9Smrg		break;
5824d9b34d9Smrg    }
5834d9b34d9Smrg    dnum=acc;
5844d9b34d9Smrg    PushNum(dnum);
5854d9b34d9Smrg  }
5864d9b34d9Smrg
5874d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
5884d9b34d9Smrg  DrawDisplay();
5894d9b34d9Smrg}
5904d9b34d9Smrg
5914d9b34d9Smrgvoid
5924d9b34d9Smrglparf(void)
5934d9b34d9Smrg{
5944d9b34d9Smrg  flagINV=0;
5954d9b34d9Smrg  PushOp(kLPAR);
5964d9b34d9Smrg  flagPAREN++;
5974d9b34d9Smrg  DrawDisplay();
5984d9b34d9Smrg}
5994d9b34d9Smrg
6004d9b34d9Smrgvoid
6014d9b34d9Smrgrollf(void)
6024d9b34d9Smrg{
6034d9b34d9Smrg  if (!entered)
6044d9b34d9Smrg    return;
6054d9b34d9Smrg  if (entered==1)
6064d9b34d9Smrg    parse_double(dispstr, "%lf", &dnum);
6074d9b34d9Smrg  entered = 2;
6084d9b34d9Smrg  lift_enabled = 1;
6094d9b34d9Smrg  RollNum(flagINV);
6104d9b34d9Smrg  flagINV=0;
6114d9b34d9Smrg  clrdisp++;
6124d9b34d9Smrg  sprintf(dispstr, "%.8g", dnum);
6134d9b34d9Smrg  DrawDisplay();
6144d9b34d9Smrg}
6154d9b34d9Smrg
6164d9b34d9Smrgvoid
6174d9b34d9Smrgrparf(void)
6184d9b34d9Smrg{
6194d9b34d9Smrg  flagINV=0;
6204d9b34d9Smrg  if (!entered)
6214d9b34d9Smrg    return;
6224d9b34d9Smrg
6234d9b34d9Smrg  if (!flagPAREN)
6244d9b34d9Smrg    return;
6254d9b34d9Smrg
6264d9b34d9Smrg  clrdisp++;
6274d9b34d9Smrg  Dpoint=exponent=0;
6284d9b34d9Smrg
6294d9b34d9Smrg  if (entered==1)
6304d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
6314d9b34d9Smrg  entered=2;
6324d9b34d9Smrg
6334d9b34d9Smrg  PushNum(dnum);
6344d9b34d9Smrg  while (!isopempty() && (lastop=PopOp())!=kLPAR) {
6354d9b34d9Smrg    /* do all pending ops, back to left paren */
6364d9b34d9Smrg    dnum=PopNum();
6374d9b34d9Smrg    acc=PopNum();
6384d9b34d9Smrg    switch (lastop) {
6394d9b34d9Smrg    case kADD:  acc += dnum;
6404d9b34d9Smrg		break;
6414d9b34d9Smrg    case kSUB:  acc -= dnum;
6424d9b34d9Smrg		break;
6434d9b34d9Smrg    case kMUL:  acc *= dnum;
6444d9b34d9Smrg		break;
6454d9b34d9Smrg    case kDIV:  acc /= dnum;
6464d9b34d9Smrg		break;
6474d9b34d9Smrg    case kPOW:  acc = pow(acc,dnum);
6484d9b34d9Smrg		break;
6494d9b34d9Smrg    }
6504d9b34d9Smrg    dnum=acc;
6514d9b34d9Smrg    PushNum(dnum);
6524d9b34d9Smrg  }
6534d9b34d9Smrg  (void) PopNum();
6544d9b34d9Smrg  flagPAREN--;
6554d9b34d9Smrg  entered=2;
6564d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
6574d9b34d9Smrg  DrawDisplay();
6584d9b34d9Smrg}
6594d9b34d9Smrg
6604d9b34d9Smrgvoid
6614d9b34d9Smrgdrgf(void)
6624d9b34d9Smrg{
6634d9b34d9Smrg  if (flagINV) {
6644d9b34d9Smrg    if (entered==1)
6654d9b34d9Smrg      parse_double(dispstr,"%lf",&dnum);
6664d9b34d9Smrg    switch (drgmode) {
6674d9b34d9Smrg    case DEG:  dnum=dnum*PI/180.0;    break;
6684d9b34d9Smrg    case RAD:  dnum=dnum*200.0/PI;    break;
6694d9b34d9Smrg    case GRAD: dnum=dnum*90.0/100.0;  break;
6704d9b34d9Smrg    }
6714d9b34d9Smrg    entered=2;
6724d9b34d9Smrg    clrdisp=1;
6734d9b34d9Smrg    flagINV=0;
6744d9b34d9Smrg    sprintf(dispstr,"%.8g",dnum);
6754d9b34d9Smrg  }
6764d9b34d9Smrg
6774d9b34d9Smrg  flagINV=0;
6784d9b34d9Smrg  drgmode = (drgmode + 1) % 3;
6794d9b34d9Smrg  switch (drgmode) {
6804d9b34d9Smrg  case DEG:  drg2rad=PI / 180.0;
6814d9b34d9Smrg	     rad2drg=180.0 / PI;
6824d9b34d9Smrg	     break;
6834d9b34d9Smrg  case RAD:  drg2rad=1.0;
6844d9b34d9Smrg	     rad2drg=1.0;
6854d9b34d9Smrg	     break;
6864d9b34d9Smrg  case GRAD: drg2rad=PI / 200.0;
6874d9b34d9Smrg	     rad2drg=200.0 / PI;
6884d9b34d9Smrg	     break;
6894d9b34d9Smrg  }
6904d9b34d9Smrg  DrawDisplay();
6914d9b34d9Smrg}
6924d9b34d9Smrg
6934d9b34d9Smrgvoid
6944d9b34d9Smrginvf(void)
6954d9b34d9Smrg{
6964d9b34d9Smrg  flagINV = ~flagINV;
6974d9b34d9Smrg  DrawDisplay();
6984d9b34d9Smrg}
6994d9b34d9Smrg
7004d9b34d9Smrgvoid
7014d9b34d9Smrgmemf(int keynum)
7024d9b34d9Smrg{
7034d9b34d9Smrg    memop = keynum;
7044d9b34d9Smrg    if (entered==1)
7054d9b34d9Smrg      parse_double(dispstr,"%lf",&dnum);
7064d9b34d9Smrg    entered = 2;
7074d9b34d9Smrg    clrdisp++;
7084d9b34d9Smrg    lift_enabled = 0;
7094d9b34d9Smrg}
7104d9b34d9Smrg
7114d9b34d9Smrgvoid
7124d9b34d9Smrgoneop(int keynum)
7134d9b34d9Smrg{
7144d9b34d9Smrg  int i,j;
7154d9b34d9Smrg  double dtmp;
7164d9b34d9Smrg
7174d9b34d9Smrg  if (entered==1)
7184d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
7194d9b34d9Smrg  entered = 2;
7204d9b34d9Smrg
7214d9b34d9Smrg  switch (keynum) {  /* do the actual math fn. */
7224d9b34d9Smrg  case kE:     if (rpn && memop != kENTR) PushNum(dnum); dnum=E;  break;
7234d9b34d9Smrg  case kPI:    if (rpn && memop != kENTR) PushNum(dnum); dnum=PI;  break;
7244d9b34d9Smrg  case kRECIP: dnum=1.0/dnum;  break;
7254d9b34d9Smrg  case kSQR:   flagINV = !flagINV; /* fall through to */
7264d9b34d9Smrg  case kSQRT:  if (flagINV) dnum=dnum*dnum;
7274d9b34d9Smrg	       else dnum=sqrt(dnum);
7284d9b34d9Smrg	       break;
7294d9b34d9Smrg  case k10X:   flagINV = !flagINV; /* fall through to */
7304d9b34d9Smrg  case kLOG:   if (flagINV) dnum=pow(10.0,dnum);
7314d9b34d9Smrg  	       else dnum=log10(dnum);
7324d9b34d9Smrg	       break;
7334d9b34d9Smrg  case kEXP:   flagINV = !flagINV; /* fall through to */
7344d9b34d9Smrg  case kLN:    if (flagINV) dnum=exp(dnum);
7354d9b34d9Smrg	       else dnum=log(dnum);
7364d9b34d9Smrg	       break;
7374d9b34d9Smrg  case kSIN:   if (flagINV) dnum=asin(dnum)*rad2drg;
7384d9b34d9Smrg	       else dnum=sin(dnum*drg2rad);
7394d9b34d9Smrg	       break;
7404d9b34d9Smrg  case kCOS:   if (flagINV) dnum=acos(dnum)*rad2drg;
7414d9b34d9Smrg	       else dnum=cos(dnum*drg2rad);
7424d9b34d9Smrg	       break;
7434d9b34d9Smrg  case kTAN:   if (flagINV) dnum=atan(dnum)*rad2drg;
7444d9b34d9Smrg	       else dnum=tan(dnum*drg2rad);
7454d9b34d9Smrg	       break;
7464d9b34d9Smrg  case kSTO:   mem[0]=dnum;  flagM=!(mem[0]==0.0);  break;
7474d9b34d9Smrg  case kRCL:   if (rpn && lift_enabled) PushNum(dnum);
7484d9b34d9Smrg               dnum=mem[0];  flagM=!(mem[0]==0.0);  break;
7494d9b34d9Smrg  case kSUM:   mem[0]+=dnum; flagM=!(mem[0]==0.0);  break;
7504d9b34d9Smrg  case kEXC:   dtmp=dnum; dnum=mem[0];  mem[0]=dtmp;
7514d9b34d9Smrg	       flagM=!(mem[0]==0.0);  break;
7524d9b34d9Smrg  case kFACT:  if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) {
7534d9b34d9Smrg		 strcpy(dispstr,"error");
7544d9b34d9Smrg		 entered=3;
7554d9b34d9Smrg		 break;
7564d9b34d9Smrg	       }
7578512f934Smrg	       dtmp = floor(dnum); i = dtmp;
7584d9b34d9Smrg	       for (j=1,dnum=1.0; j<=i; j++)
7594d9b34d9Smrg		 dnum*=(float) j;
7604d9b34d9Smrg	       break;
7614d9b34d9Smrg  }
7624d9b34d9Smrg
7634d9b34d9Smrg  if (entered==3) {  /* error */
7644d9b34d9Smrg    DrawDisplay();
7654d9b34d9Smrg    return;
7664d9b34d9Smrg  }
7674d9b34d9Smrg
7684d9b34d9Smrg  memop = keynum;
7694d9b34d9Smrg  entered=2;
7704d9b34d9Smrg  clrdisp=1;
7714d9b34d9Smrg  flagINV=0;
7724d9b34d9Smrg  lift_enabled = 1;
7734d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
7744d9b34d9Smrg  DrawDisplay();
7754d9b34d9Smrg}
7764d9b34d9Smrg
7774d9b34d9Smrgvoid
7784d9b34d9Smrgofff(void)
7794d9b34d9Smrg{
7804d9b34d9Smrg  /* full reset */
7814d9b34d9Smrg  int i;
7824d9b34d9Smrg  ResetCalc();
7834d9b34d9Smrg  entered=clrdisp=1;
7844d9b34d9Smrg  lift_enabled = 0;
7854d9b34d9Smrg  dnum=mem[0]=0.0;
7864d9b34d9Smrg  if (rpn)
7874d9b34d9Smrg      for (i=1; i < XCALC_MEMORY; i++)
7884d9b34d9Smrg	  mem[i]=0.0;
7894d9b34d9Smrg  exponent=Dpoint=0;
7904d9b34d9Smrg  DrawDisplay();
7914d9b34d9Smrg}
7924d9b34d9Smrg
7934d9b34d9Smrg
7944d9b34d9Smrg#define STACKMAX 32
7954d9b34d9Smrgstatic int opstack[STACKMAX];
7964d9b34d9Smrgstatic int opsp;
7974d9b34d9Smrgstatic double numstack[STACKMAX];
7984d9b34d9Smrgstatic int numsp;
7994d9b34d9Smrg
8004d9b34d9Smrg
8014d9b34d9Smrg/*******/
8024d9b34d9Smrgstatic void
8038512f934SmrgPushOp(int op)
8044d9b34d9Smrg/*******/
8054d9b34d9Smrg{
8064d9b34d9Smrg  if (opsp==STACKMAX) {strcpy(dispstr,"stack error");  entered=3;}
8074d9b34d9Smrg  else opstack[opsp++]=op;
8084d9b34d9Smrg}
8094d9b34d9Smrg
8104d9b34d9Smrg/*******/
8114d9b34d9Smrgstatic int
8124d9b34d9SmrgPopOp(void)
8134d9b34d9Smrg/*******/
8144d9b34d9Smrg{
8154d9b34d9Smrg  if (opsp==0) {
8164d9b34d9Smrg      strcpy(dispstr,"stack error");
8174d9b34d9Smrg      entered=3;
8184d9b34d9Smrg      return(kNOP);
8194d9b34d9Smrg  } else
8204d9b34d9Smrg    return(opstack[--opsp]);
8214d9b34d9Smrg}
8224d9b34d9Smrg
8234d9b34d9Smrg/*******/
8244d9b34d9Smrgstatic int
8254d9b34d9Smrgisopempty(void)
8264d9b34d9Smrg/*******/
8274d9b34d9Smrg{
8284d9b34d9Smrg  return( opsp ? 0 : 1 );
8294d9b34d9Smrg}
8304d9b34d9Smrg
8314d9b34d9Smrg#ifdef DEBUG
8324d9b34d9Smrgstatic void
8338512f934Smrgshowstack(char *string)
8344d9b34d9Smrg{
8354d9b34d9Smrg    fprintf(stderr, "%s: %lf %lf %lf\n", string, numstack[0], numstack[1],
8364d9b34d9Smrg	    numstack[2]);
8374d9b34d9Smrg}
8384d9b34d9Smrg#endif
8394d9b34d9Smrg
8404d9b34d9Smrg/*******/
8414d9b34d9Smrgstatic void
8428512f934SmrgPushNum(double num)
8434d9b34d9Smrg/*******/
8444d9b34d9Smrg{
8454d9b34d9Smrg  if (rpn) {
8464d9b34d9Smrg      numstack[2] = numstack[1];
8474d9b34d9Smrg      numstack[1] = numstack[0];
8484d9b34d9Smrg      numstack[0] = num;
8494d9b34d9Smrg      return;
8504d9b34d9Smrg  }
8514d9b34d9Smrg  if (numsp==STACKMAX) {
8524d9b34d9Smrg      strcpy(dispstr,"stack error");
8534d9b34d9Smrg      entered=3;
8544d9b34d9Smrg  } else
8554d9b34d9Smrg    numstack[numsp++]=num;
8564d9b34d9Smrg}
8574d9b34d9Smrg
8584d9b34d9Smrg/*******/
8594d9b34d9Smrgstatic double
8604d9b34d9SmrgPopNum(void)
8614d9b34d9Smrg/*******/
8624d9b34d9Smrg{
8634d9b34d9Smrg    if (rpn) {
8644d9b34d9Smrg	double tmp = numstack[0];
8654d9b34d9Smrg	numstack[0] = numstack[1];
8664d9b34d9Smrg	numstack[1] = numstack[2];
8674d9b34d9Smrg	return(tmp);
8684d9b34d9Smrg    }
8694d9b34d9Smrg    if (numsp==0) {
8704d9b34d9Smrg	strcpy(dispstr,"stack error");
8714d9b34d9Smrg	entered=3;
8724d9b34d9Smrg	return 0.0;
8734d9b34d9Smrg    } else
8744d9b34d9Smrg      return(numstack[--numsp]);
8754d9b34d9Smrg}
8764d9b34d9Smrg
8774d9b34d9Smrg/*******/
8784d9b34d9Smrgstatic void
8794d9b34d9SmrgRollNum(int dir)
8804d9b34d9Smrg/*******/
8814d9b34d9Smrg{
8824d9b34d9Smrg    double tmp;
8834d9b34d9Smrg
8844d9b34d9Smrg    if (dir) {				/* roll up */
8854d9b34d9Smrg	tmp         = dnum;
8864d9b34d9Smrg	dnum        = numstack[2];
8874d9b34d9Smrg	numstack[2] = numstack[1];
8884d9b34d9Smrg	numstack[1] = numstack[0];
8894d9b34d9Smrg	numstack[0] = tmp;
8904d9b34d9Smrg    } else {				/* roll down */
8914d9b34d9Smrg	tmp         = dnum;
8924d9b34d9Smrg	dnum        = numstack[0];
8934d9b34d9Smrg	numstack[0] = numstack[1];
8944d9b34d9Smrg	numstack[1] = numstack[2];
8954d9b34d9Smrg	numstack[2] = tmp;
8964d9b34d9Smrg    }
8974d9b34d9Smrg}
8984d9b34d9Smrg
8994d9b34d9Smrg
9004d9b34d9Smrg/*******/
9014d9b34d9Smrgstatic void
9024d9b34d9SmrgClearStacks(void)
9034d9b34d9Smrg/*******/
9044d9b34d9Smrg{
9054d9b34d9Smrg    if (rpn)
9064d9b34d9Smrg      numstack[0] = numstack[1] = numstack[2] = 0.;
9074d9b34d9Smrg    opsp=numsp=0;
9084d9b34d9Smrg}
9094d9b34d9Smrg
9104d9b34d9Smrg
9114d9b34d9Smrg/*******/
9124d9b34d9Smrgstatic int
9138512f934Smrgpriority(int op)
9144d9b34d9Smrg/*******/
9154d9b34d9Smrg{
9164d9b34d9Smrg    switch (op) {
9174d9b34d9Smrg        case kPOW: return(2);
9184d9b34d9Smrg        case kMUL:
9194d9b34d9Smrg        case kDIV: return(1);
9204d9b34d9Smrg        case kADD:
9214d9b34d9Smrg        case kSUB: return(0);
9224d9b34d9Smrg        }
9234d9b34d9Smrg    return 0;
9244d9b34d9Smrg}
9254d9b34d9Smrg
9264d9b34d9Smrg
9274d9b34d9Smrg/********/
9284d9b34d9Smrgvoid
9294d9b34d9SmrgResetCalc(void)
9304d9b34d9Smrg/********/
9314d9b34d9Smrg{
9324d9b34d9Smrg    flagM=flagINV=flagPAREN=0;  drgmode=DEG;
9334d9b34d9Smrg    setflag(XCalc_MEMORY, False);
9344d9b34d9Smrg    setflag(XCalc_INVERSE, False);
9354d9b34d9Smrg    setflag(XCalc_PAREN, False);
9364d9b34d9Smrg    setflag(XCalc_RADIAN, False);
9374d9b34d9Smrg    setflag(XCalc_GRADAM, False);
9384d9b34d9Smrg    setflag(XCalc_DEGREE, True);
9394d9b34d9Smrg    strcpy(dispstr,"0");
9404d9b34d9Smrg    draw(dispstr);
9414d9b34d9Smrg    ClearStacks();
9424d9b34d9Smrg    drg2rad=PI/180.0;
9434d9b34d9Smrg    rad2drg=180.0/PI;
9444d9b34d9Smrg}
945