math.c revision fc5a3af9
112e1d9cbSmrg/* 24d9b34d9Smrg * math.c - mathematics functions for a hand calculator under X 34d9b34d9Smrg * 44d9b34d9Smrg * Author: John H. Bradley, University of Pennsylvania 54d9b34d9Smrg * (bradley@cis.upenn.edu) 64d9b34d9Smrg * March, 1987 74d9b34d9Smrg * 84d9b34d9Smrg * RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena 94d9b34d9Smrg * 104d9b34d9Smrg * Modified to be a client of the Xt toolkit and the Athena widget set by 11498372abSmrg * Donna Converse, MIT X Consortium. This is all that remains of the 124d9b34d9Smrg * original calculator, and it still needs to be rewritten. The HP 13498372abSmrg * functionality should be separated from the TI functionality. 144d9b34d9Smrg * Beware the HP functions: there are still errors here. 154d9b34d9Smrg * 164d9b34d9Smrg * Geoffrey Coram fixed most of the HP mode bugs. 174d9b34d9Smrg */ 184d9b34d9Smrg 194d9b34d9Smrg#include "xcalc.h" 204d9b34d9Smrg 2119d64aeeSmrg#ifndef M_PI /* sometimes defined in math.h */ 2219d64aeeSmrg#define M_PI 3.14159265358979323846 234d9b34d9Smrg#endif 2419d64aeeSmrg 2519d64aeeSmrg#ifndef M_E /* sometimes defined in math.h */ 2619d64aeeSmrg#define M_E 2.7182818284590452354 2719d64aeeSmrg#endif 2819d64aeeSmrg 294d9b34d9Smrg#define MAXDISP 11 304d9b34d9Smrg#define DEG 0 /* DRG mode. used for trig calculations */ 314d9b34d9Smrg#define RAD 1 324d9b34d9Smrg#define GRAD 2 3319d64aeeSmrg 344d9b34d9Smrg#define True 1 354d9b34d9Smrg#define False 0 364d9b34d9Smrg 374d9b34d9Smrg#ifndef IEEE 388512f934Smrgjmp_buf env; 394d9b34d9Smrg#endif 404d9b34d9Smrg 41498372abSmrg 424d9b34d9Smrg/* This section is all of the state machine that implements the calculator 434d9b34d9Smrg * functions. Much of it is shared between the infix and rpn modes. 444d9b34d9Smrg */ 454d9b34d9Smrg 462256ab8cSmrgstatic int flagINV, flagPAREN, flagM, drgmode, numbase; /* display flags */ 474d9b34d9Smrg 4819d64aeeSmrgstatic double drg2rad=M_PI/180.0; /* Conversion factors for trig funcs */ 4919d64aeeSmrgstatic double rad2drg=180.0/M_PI; 504d9b34d9Smrgstatic int entered=1; /* true if display contains a valid number. 514d9b34d9Smrg if==2, then use 'dnum', rather than the string 52498372abSmrg stored in the display. (for accuracy) 534d9b34d9Smrg if==3, then error occurred, only CLR & AC work */ 544d9b34d9Smrg/* entered seems to be overloaded - dmc */ 554d9b34d9Smrgstatic int lift_enabled = 0; /* for rpn mode only */ 564d9b34d9Smrg 574d9b34d9Smrgstatic int CLR =0; /* CLR clears display. if 1, clears acc, also */ 584d9b34d9Smrgstatic int Dpoint=0; /* to prevent using decimal pt twice in a # */ 594d9b34d9Smrgstatic int clrdisp=1; /* if true clears display before entering # */ 604d9b34d9Smrgstatic int lastop =kCLR; 614d9b34d9Smrgstatic int memop =kCLR; 624d9b34d9Smrgstatic int exponent=0; 634d9b34d9Smrgstatic double acc =0.0; 644d9b34d9Smrgstatic double dnum=0.0; 654d9b34d9Smrg#define XCALC_MEMORY 10 664d9b34d9Smrgstatic double mem[XCALC_MEMORY] = { 0.0 }; 674d9b34d9Smrg 684d9b34d9Smrgstatic void DrawDisplay(void); 694d9b34d9Smrgstatic void PushOp(int op); 704d9b34d9Smrgstatic int PopOp(void); 714d9b34d9Smrgstatic int isopempty(void); 724d9b34d9Smrg#ifdef DEBUG 734d9b34d9Smrgstatic void showstack(char *string); 744d9b34d9Smrg#endif 754d9b34d9Smrgstatic void PushNum(double num); 764d9b34d9Smrgstatic double PopNum(void); 774d9b34d9Smrgstatic void RollNum(int dir); 784d9b34d9Smrgstatic void ClearStacks(void); 794d9b34d9Smrgstatic int priority(int op); 804d9b34d9Smrg 8119d64aeeSmrg#ifndef HAVE_STRLCPY 8219d64aeeSmrg/* Close enough for the short strings copied in xcalc */ 8319d64aeeSmrgstatic inline size_t 8419d64aeeSmrgstrlcpy(char *dst, const char *src, size_t size) 8519d64aeeSmrg{ 8619d64aeeSmrg strncpy(dst, src, size); 8719d64aeeSmrg dst[size - 1] = '\0'; 8819d64aeeSmrg return strlen(src); 8919d64aeeSmrg} 9019d64aeeSmrg#endif 9119d64aeeSmrg 924d9b34d9Smrg/* 934d9b34d9Smrg * The following is to deal with the unfortunate assumption that if errno 94498372abSmrg * is non-zero then an error has occurred. On some systems (e.g. Ultrix), 954d9b34d9Smrg * sscanf will call lower level routines that will set errno. 964d9b34d9Smrg */ 974d9b34d9Smrgstatic void 982256ab8cSmrgparse_double(double *dp) 994d9b34d9Smrg{ 1002256ab8cSmrg unsigned long n = 0; 1014d9b34d9Smrg int olderrno = errno; 1024d9b34d9Smrg 1032256ab8cSmrg switch (numbase) { 1042256ab8cSmrg case 8: 105fc5a3af9Smrg sscanf(dispstr, "%lo", &n); 1062256ab8cSmrg *dp = (double)n; 1072256ab8cSmrg break; 1082256ab8cSmrg case 16: 109fc5a3af9Smrg sscanf(dispstr, "%lX", &n); 1102256ab8cSmrg *dp = (double)n; 1112256ab8cSmrg break; 1122256ab8cSmrg default: 113fc5a3af9Smrg sscanf(dispstr, "%lf", dp); 1142256ab8cSmrg } 1152256ab8cSmrg 1164d9b34d9Smrg errno = olderrno; 1174d9b34d9Smrg return; 1184d9b34d9Smrg} 1194d9b34d9Smrg 1202256ab8cSmrg/** 1212256ab8cSmrg * Format the given double according to the 1222256ab8cSmrg * selected number base. 1232256ab8cSmrg */ 1242256ab8cSmrgstatic void 1252256ab8cSmrgformat_double(double n) 1262256ab8cSmrg{ 1272256ab8cSmrg switch (numbase) { 1282256ab8cSmrg case 8: 1292256ab8cSmrg snprintf(dispstr, sizeof(dispstr), "%lo", (long)n); 1302256ab8cSmrg break; 1312256ab8cSmrg case 16: 1322256ab8cSmrg snprintf(dispstr, sizeof(dispstr), "%lX", (long)n); 1332256ab8cSmrg break; 1342256ab8cSmrg default: 1352256ab8cSmrg snprintf(dispstr, sizeof(dispstr), "%.8g", n); 1362256ab8cSmrg } 1372256ab8cSmrg} 1384d9b34d9Smrg 1394d9b34d9Smrg/*********************************/ 1408512f934Smrgint pre_op(int keynum) 1414d9b34d9Smrg{ 1424d9b34d9Smrg if (keynum==-1) return(0); 143498372abSmrg 1444d9b34d9Smrg errno = 0; /* for non-IEEE machines */ 1454d9b34d9Smrg 1464d9b34d9Smrg if ( (entered==3) && !(keynum==kCLR || keynum==kOFF)) { 1474d9b34d9Smrg if (rpn) { 1484d9b34d9Smrg clrdisp++; 1494d9b34d9Smrg } else { 1504d9b34d9Smrg ringbell(); 1514d9b34d9Smrg return(1); /* the intent was probably not to do the operation */ 1524d9b34d9Smrg } 1534d9b34d9Smrg } 1544d9b34d9Smrg 1554d9b34d9Smrg if (keynum != kCLR) CLR=0; 1564d9b34d9Smrg return(0); 1574d9b34d9Smrg} 1584d9b34d9Smrg 1594d9b34d9Smrg#ifndef IEEE 1604d9b34d9Smrg 1614d9b34d9Smrg/* cannot assign result of setjmp under ANSI C, use global instead */ 1624d9b34d9Smrgstatic volatile int SignalKind; 1634d9b34d9Smrg 1648512f934Smrgvoid fail_op(void) 1654d9b34d9Smrg{ 1664d9b34d9Smrg if (SignalKind == SIGFPE) 16719d64aeeSmrg strlcpy(dispstr, "math error", sizeof(dispstr)); 1688512f934Smrg else if (SignalKind == SIGILL) 16919d64aeeSmrg strlcpy(dispstr, "illegal operand", sizeof(dispstr)); 1704d9b34d9Smrg 1714d9b34d9Smrg entered=3; 1724d9b34d9Smrg DrawDisplay(); 1734d9b34d9Smrg return; 1744d9b34d9Smrg} 1754d9b34d9Smrg 1764d9b34d9Smrg/*ARGSUSED*/ 17719d64aeeSmrgvoid fperr(int sig) 1784d9b34d9Smrg{ 1794d9b34d9Smrg#if defined(SYSV) || defined(SVR4) || defined(linux) 1808512f934Smrg signal(SIGFPE, fperr); 1814d9b34d9Smrg#endif 1824d9b34d9Smrg SignalKind = sig; 1834d9b34d9Smrg longjmp(env,1); 1844d9b34d9Smrg} 1854d9b34d9Smrg 1864d9b34d9Smrg/* for VAX BSD4.3 */ 1874d9b34d9Smrg/*ARGSUSED*/ 18819d64aeeSmrgvoid illerr(int sig) 1894d9b34d9Smrg{ 1904d9b34d9Smrg /* not reset when caught? */ 1918512f934Smrg signal(SIGILL, illerr); 1924d9b34d9Smrg 1934d9b34d9Smrg SignalKind = sig; 1944d9b34d9Smrg longjmp(env,1); 1954d9b34d9Smrg} 1964d9b34d9Smrg 1974d9b34d9Smrg#endif /* not IEEE */ 1984d9b34d9Smrg 1994d9b34d9Smrg 2008512f934Smrgvoid post_op(void) 2014d9b34d9Smrg{ 2024d9b34d9Smrg#ifdef DEBUG 2034d9b34d9Smrg showstack("\0"); 2044d9b34d9Smrg#endif 2054d9b34d9Smrg#ifndef IEEE 2064d9b34d9Smrg if (errno) { 20719d64aeeSmrg strlcpy(dispstr, "error", sizeof(dispstr)); 2084d9b34d9Smrg DrawDisplay(); 2094d9b34d9Smrg entered=3; 2104d9b34d9Smrg errno=0; 2114d9b34d9Smrg } 2124d9b34d9Smrg#endif 2134d9b34d9Smrg} 2142256ab8cSmrg 2154d9b34d9Smrg/*-------------------------------------------------------------------------*/ 2164d9b34d9Smrgstatic void 2174d9b34d9SmrgDrawDisplay(void) 2184d9b34d9Smrg{ 2192256ab8cSmrg if (strlen(dispstr) >= MAXDISP) { /* strip out some decimal digits */ 2202256ab8cSmrg char *estr = index(dispstr,'e'); /* search for exponent part */ 2214d9b34d9Smrg if (!estr) dispstr[12]='\0'; /* no exp, just trunc. */ 2224d9b34d9Smrg else { 22319d64aeeSmrg char tmp[32]; 22419d64aeeSmrg if (strlen(estr) <= 4) /* leftmost 8 chars plus exponent */ 22519d64aeeSmrg snprintf(tmp, sizeof(tmp), "%.8s%s", dispstr, estr); 22619d64aeeSmrg else /* leftmost 7 chars plus exponent */ 22719d64aeeSmrg snprintf(tmp, sizeof(tmp), "%.7s%s", dispstr, estr); 22819d64aeeSmrg strlcpy(dispstr, tmp, sizeof(dispstr)); 2294d9b34d9Smrg } 23019d64aeeSmrg } 2314d9b34d9Smrg draw(dispstr); 2324d9b34d9Smrg setflag(XCalc_MEMORY, (flagM)); 2334d9b34d9Smrg setflag(XCalc_INVERSE, (flagINV)); 2344d9b34d9Smrg setflag(XCalc_DEGREE, (drgmode==DEG)); 2354d9b34d9Smrg setflag(XCalc_RADIAN, (drgmode==RAD)); 2364d9b34d9Smrg setflag(XCalc_GRADAM, (drgmode==GRAD)); 2374d9b34d9Smrg setflag(XCalc_PAREN, (flagPAREN)); 2382256ab8cSmrg setflag(XCalc_HEX, (numbase==16)); 2392256ab8cSmrg setflag(XCalc_DEC, (numbase==10)); 2402256ab8cSmrg setflag(XCalc_OCT, (numbase==8)); 2412256ab8cSmrg} 2422256ab8cSmrg 2432256ab8cSmrg/*-------------------------------------------------------------------------*/ 2442256ab8cSmrgvoid 2452256ab8cSmrgchange_base(void) 2462256ab8cSmrg{ 2472256ab8cSmrg parse_double(&dnum); 2482256ab8cSmrg 2492256ab8cSmrg if (dnum >= 0) { 2502256ab8cSmrg switch (numbase) { 2512256ab8cSmrg case 8: numbase = 10; break; 2522256ab8cSmrg case 10: numbase = 16; break; 2532256ab8cSmrg case 16: numbase = 8; break; 2542256ab8cSmrg } 2552256ab8cSmrg 2562256ab8cSmrg format_double(dnum); 2572256ab8cSmrg } else strlcpy(dispstr, "error", sizeof(dispstr)); 2582256ab8cSmrg 2592256ab8cSmrg DrawDisplay(); 2604d9b34d9Smrg} 2614d9b34d9Smrg 2624d9b34d9Smrg/*-------------------------------------------------------------------------*/ 2634d9b34d9Smrgvoid 2648512f934Smrgnumeric(int keynum) 2654d9b34d9Smrg{ 2660df20633Smrg char st[2]; 2674d9b34d9Smrg 2684d9b34d9Smrg flagINV=0; 2694d9b34d9Smrg 2704d9b34d9Smrg if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) { 2710df20633Smrg int cell = 0; 2720df20633Smrg 2734d9b34d9Smrg switch (keynum) { 2744d9b34d9Smrg case kONE: cell = 1; break; 2754d9b34d9Smrg case kTWO: cell = 2; break; 2764d9b34d9Smrg case kTHREE: cell = 3; break; 2774d9b34d9Smrg case kFOUR: cell = 4; break; 2784d9b34d9Smrg case kFIVE: cell = 5; break; 2794d9b34d9Smrg case kSIX: cell = 6; break; 2804d9b34d9Smrg case kSEVEN: cell = 7; break; 2814d9b34d9Smrg case kEIGHT: cell = 8; break; 2824d9b34d9Smrg case kNINE: cell = 9; break; 2834d9b34d9Smrg case kZERO: cell = 0; break; 2844d9b34d9Smrg } 2854d9b34d9Smrg switch (memop) { 2864d9b34d9Smrg case kSTO: 2874d9b34d9Smrg mem[cell] = dnum; 2884d9b34d9Smrg lift_enabled = 1; 2894d9b34d9Smrg entered = 2; 2904d9b34d9Smrg clrdisp++; 2914d9b34d9Smrg break; 2924d9b34d9Smrg case kRCL: 2934d9b34d9Smrg PushNum(dnum); 2944d9b34d9Smrg dnum = mem[cell]; 2952256ab8cSmrg format_double(dnum); 2964d9b34d9Smrg lift_enabled = 1; 2974d9b34d9Smrg entered = 1; 2984d9b34d9Smrg clrdisp++; 2994d9b34d9Smrg break; 3004d9b34d9Smrg case kSUM: 3014d9b34d9Smrg mem[cell] += dnum; 3024d9b34d9Smrg lift_enabled = 1; 3034d9b34d9Smrg entered = 2; 3044d9b34d9Smrg clrdisp++; 3054d9b34d9Smrg break; 3064d9b34d9Smrg } 3074d9b34d9Smrg memop = kCLR; 3084d9b34d9Smrg DrawDisplay(); 3094d9b34d9Smrg return; 3104d9b34d9Smrg } 3114d9b34d9Smrg 3124d9b34d9Smrg if (clrdisp) { 3134d9b34d9Smrg dispstr[0]='\0'; 3144d9b34d9Smrg exponent=Dpoint=0; 3154d9b34d9Smrg/* if (rpn && entered==2) 3164d9b34d9Smrg PushNum(dnum); 3174d9b34d9Smrg */ 3184d9b34d9Smrg if (rpn & lift_enabled) 3194d9b34d9Smrg PushNum(dnum); 3204d9b34d9Smrg } 3214d9b34d9Smrg if ((int) strlen(dispstr) >= MAXDISP) 3224d9b34d9Smrg return; 323498372abSmrg 3242256ab8cSmrg st[0] = '\0'; 3250df20633Smrg switch (keynum){ 3262256ab8cSmrg case kZERO: st[0] = '0'; break; 3274d9b34d9Smrg case kONE: st[0] = '1'; break; 3284d9b34d9Smrg case kTWO: st[0] = '2'; break; 3294d9b34d9Smrg case kTHREE: st[0] = '3'; break; 3304d9b34d9Smrg case kFOUR: st[0] = '4'; break; 3314d9b34d9Smrg case kFIVE: st[0] = '5'; break; 3324d9b34d9Smrg case kSIX: st[0] = '6'; break; 3334d9b34d9Smrg case kSEVEN: st[0] = '7'; break; 3342256ab8cSmrg case kEIGHT: if (numbase > 8) st[0] = '8'; break; 3352256ab8cSmrg case kNINE: if (numbase > 8) st[0] = '9'; break; 3362256ab8cSmrg case kxA: if (numbase > 10) st[0] = 'A'; break; 3372256ab8cSmrg case kxB: if (numbase > 10) st[0] = 'B'; break; 3382256ab8cSmrg case kxC: if (numbase > 10) st[0] = 'C'; break; 3392256ab8cSmrg case kxD: if (numbase > 10) st[0] = 'D'; break; 3402256ab8cSmrg case kxE: if (numbase > 10) st[0] = 'E'; break; 3412256ab8cSmrg case kxF: if (numbase > 10) st[0] = 'F'; break; 3422256ab8cSmrg } 3432256ab8cSmrg 3442256ab8cSmrg if (st[0] == '\0') 3452256ab8cSmrg return; 3462256ab8cSmrg st[1] = '\0'; 3472256ab8cSmrg strcat(dispstr,st); 3484d9b34d9Smrg 3494d9b34d9Smrg DrawDisplay(); 3504d9b34d9Smrg if (clrdisp && keynum != kZERO) 3514d9b34d9Smrg clrdisp=0; /*no leading 0s*/ 3524d9b34d9Smrg memop = keynum; 3534d9b34d9Smrg entered=1; 3544d9b34d9Smrg lift_enabled = 0; 3554d9b34d9Smrg} 3564d9b34d9Smrg 3574d9b34d9Smrgvoid 3584d9b34d9Smrgbkspf(void) 3594d9b34d9Smrg{ 3604d9b34d9Smrg 3614d9b34d9Smrg lift_enabled = 0; 3624d9b34d9Smrg 3634d9b34d9Smrg if (! flagINV) 3644d9b34d9Smrg { 3654d9b34d9Smrg if (entered!=1) { 3664d9b34d9Smrg clearf(); 3674d9b34d9Smrg return; 3684d9b34d9Smrg } 3694d9b34d9Smrg if (clrdisp) 3704d9b34d9Smrg return; 3714d9b34d9Smrg if ((int) strlen(dispstr) > 0) { 3724d9b34d9Smrg#ifndef X_LOCALE 3734d9b34d9Smrg const char *dp = localeconv()->decimal_point; 3744d9b34d9Smrg size_t dp_len = strlen(dp); 3754d9b34d9Smrg size_t ds_len = strlen(dispstr); 3764d9b34d9Smrg if (ds_len >= dp_len && strcmp(dispstr + ds_len - dp_len, dp) == 0) 3774d9b34d9Smrg Dpoint=0; 3784d9b34d9Smrg#else 3794d9b34d9Smrg if (dispstr[strlen(dispstr)-1] == '.') 3804d9b34d9Smrg Dpoint=0; 381498372abSmrg#endif 3824d9b34d9Smrg dispstr[strlen(dispstr)-1] = 0; 3834d9b34d9Smrg } 3844d9b34d9Smrg if (strlen(dispstr) == 0) { 3854d9b34d9Smrg strcat(dispstr, "0"); 3864d9b34d9Smrg clrdisp++; 3874d9b34d9Smrg } 3884d9b34d9Smrg } 3894d9b34d9Smrg else 3904d9b34d9Smrg { 39119d64aeeSmrg strlcpy(dispstr, "0", sizeof(dispstr)); 3924d9b34d9Smrg dnum = 0.0; 3934d9b34d9Smrg clrdisp++; 3944d9b34d9Smrg flagINV = 0; 3954d9b34d9Smrg } 3964d9b34d9Smrg DrawDisplay(); 3974d9b34d9Smrg} 3984d9b34d9Smrg 3994d9b34d9Smrgvoid 4004d9b34d9Smrgdecf(void) 4014d9b34d9Smrg{ 4024d9b34d9Smrg flagINV=0; 4034d9b34d9Smrg if (clrdisp) { 4044d9b34d9Smrg if (rpn && lift_enabled) 4054d9b34d9Smrg PushNum(dnum); 40619d64aeeSmrg strlcpy(dispstr, "0", sizeof(dispstr)); 4074d9b34d9Smrg } 4084d9b34d9Smrg if (!Dpoint) { 4094d9b34d9Smrg#ifndef X_LOCALE 4104d9b34d9Smrg strcat(dispstr, localeconv()->decimal_point); 4114d9b34d9Smrg#else 4124d9b34d9Smrg strcat(dispstr, "."); 4134d9b34d9Smrg#endif 4144d9b34d9Smrg DrawDisplay(); 4154d9b34d9Smrg Dpoint++; 4164d9b34d9Smrg } 4174d9b34d9Smrg clrdisp=0; 4184d9b34d9Smrg entered=1; 4194d9b34d9Smrg} 4204d9b34d9Smrg 4214d9b34d9Smrgvoid 4224d9b34d9Smrgeef(void) 4234d9b34d9Smrg{ 4244d9b34d9Smrg flagINV=0; 4254d9b34d9Smrg if (clrdisp) { 4264d9b34d9Smrg if (rpn && lift_enabled) 4274d9b34d9Smrg PushNum(dnum); 42819d64aeeSmrg strlcpy(dispstr, rpn ? "1" : "0", sizeof(dispstr)); 4294d9b34d9Smrg } 4304d9b34d9Smrg if (!exponent) { 4314d9b34d9Smrg strcat(dispstr,"E+"); 4324d9b34d9Smrg DrawDisplay(); 4334d9b34d9Smrg exponent=strlen(dispstr)-1; /* where the '-' goes */ 4344d9b34d9Smrg } 4354d9b34d9Smrg clrdisp=0; 4364d9b34d9Smrg entered=1; 4374d9b34d9Smrg} 4384d9b34d9Smrg 4394d9b34d9Smrgvoid 4404d9b34d9Smrgclearf(void) 4414d9b34d9Smrg{ 4424d9b34d9Smrg flagINV=0; 4434d9b34d9Smrg if (CLR && !rpn) { /* clear all */ 4444d9b34d9Smrg ClearStacks(); 4454d9b34d9Smrg flagPAREN=0; 4464d9b34d9Smrg } 4474d9b34d9Smrg CLR++; 4484d9b34d9Smrg exponent=Dpoint=0; 4494d9b34d9Smrg clrdisp=1; 4504d9b34d9Smrg entered=1; 45119d64aeeSmrg strlcpy(dispstr, "0", sizeof(dispstr)); 4524d9b34d9Smrg DrawDisplay(); 4534d9b34d9Smrg} 4544d9b34d9Smrg 4554d9b34d9Smrgvoid 4564d9b34d9Smrgnegf(void) 4574d9b34d9Smrg{ 4584d9b34d9Smrg flagINV=0; 4594d9b34d9Smrg if (exponent) { /* neg the exponent */ 4604d9b34d9Smrg if (dispstr[exponent]=='-') 4614d9b34d9Smrg dispstr[exponent]='+'; 4624d9b34d9Smrg else 4634d9b34d9Smrg dispstr[exponent]='-'; 4644d9b34d9Smrg DrawDisplay(); 4654d9b34d9Smrg return; 4664d9b34d9Smrg } 4674d9b34d9Smrg 4684d9b34d9Smrg if (strcmp("0",dispstr)==0) 4694d9b34d9Smrg return; /* don't neg a zero */ 4704d9b34d9Smrg if (dispstr[0]=='-') /* already neg-ed */ 4714d9b34d9Smrg strcpy(dispstr,dispstr+1); /* move str left once */ 4724d9b34d9Smrg else { /* not neg-ed. add a '-' */ 4734d9b34d9Smrg char tmp[32]; 47419d64aeeSmrg snprintf(tmp, sizeof(tmp), "-%s", dispstr); 47519d64aeeSmrg strlcpy(dispstr, tmp, sizeof(dispstr)); 4764d9b34d9Smrg } 4774d9b34d9Smrg if (entered==2) 4784d9b34d9Smrg dnum = -1.0 * dnum; 4794d9b34d9Smrg DrawDisplay(); 4804d9b34d9Smrg} 4814d9b34d9Smrg 4824d9b34d9Smrg/* Two operand functions for infix calc */ 4834d9b34d9Smrgvoid 4844d9b34d9Smrgtwoop(int keynum) 4854d9b34d9Smrg{ 4864d9b34d9Smrg if (flagINV) { 4874d9b34d9Smrg flagINV=0; 4884d9b34d9Smrg DrawDisplay(); 4894d9b34d9Smrg } 4904d9b34d9Smrg 4914d9b34d9Smrg if (!entered) { /* something like "5+*" */ 4924d9b34d9Smrg if (!isopempty()) 493fc5a3af9Smrg PopOp(); /* replace the prev op */ 4944d9b34d9Smrg PushOp(keynum); /* with the new one */ 4954d9b34d9Smrg return; 4964d9b34d9Smrg } 497498372abSmrg 4984d9b34d9Smrg if (entered==1) 4992256ab8cSmrg parse_double(&dnum); 5004d9b34d9Smrg 5014d9b34d9Smrg clrdisp=CLR=1; 5024d9b34d9Smrg entered=Dpoint=exponent=0; 5034d9b34d9Smrg 5044d9b34d9Smrg if (!isopempty()) { /* there was a previous op */ 5054d9b34d9Smrg lastop=PopOp(); /* get it */ 5064d9b34d9Smrg 5074d9b34d9Smrg if (lastop==kLPAR) { /* put it back */ 5084d9b34d9Smrg PushOp(kLPAR); 5094d9b34d9Smrg PushOp(keynum); 5104d9b34d9Smrg PushNum(dnum); 5114d9b34d9Smrg return; 5124d9b34d9Smrg } 5134d9b34d9Smrg 5144d9b34d9Smrg /* now, if the current op (keynum) is of 5154d9b34d9Smrg higher priority than the lastop, the current 516498372abSmrg op and number are just pushed on top 5172256ab8cSmrg Priorities: (Y^X) > *,/ > +,- > >>,<< > & > ^ > ~ */ 518498372abSmrg 5194d9b34d9Smrg if (priority(keynum) > priority(lastop)) { 5204d9b34d9Smrg PushNum(dnum); 5214d9b34d9Smrg PushOp(lastop); 5224d9b34d9Smrg PushOp(keynum); 5234d9b34d9Smrg } else { /* execute lastop on lastnum and dnum, push 5244d9b34d9Smrg result and current op on stack */ 5254d9b34d9Smrg acc=PopNum(); 5264d9b34d9Smrg switch (lastop) { /* perform the operation */ 5274d9b34d9Smrg case kADD: acc += dnum; break; 5284d9b34d9Smrg case kSUB: acc -= dnum; break; 5294d9b34d9Smrg case kMUL: acc *= dnum; break; 5304d9b34d9Smrg case kDIV: acc /= dnum; break; 5314d9b34d9Smrg case kPOW: acc = pow(acc,dnum); break; 5322256ab8cSmrg case kMOD: acc = (long)acc % (long)dnum; break; 5332256ab8cSmrg case kAND: acc = (long)acc & (long)dnum; break; 5342256ab8cSmrg case kOR: acc = (long)acc | (long)dnum; break; 5352256ab8cSmrg case kXOR: acc = (long)acc ^ (long)dnum; break; 5362256ab8cSmrg case kSHL: acc = (long)acc << (long)dnum; break; 5372256ab8cSmrg case kSHR: acc = (long)acc >> (long)dnum; break; 5382256ab8cSmrg } 5392256ab8cSmrg 5404d9b34d9Smrg PushNum(acc); 5414d9b34d9Smrg PushOp(keynum); 5422256ab8cSmrg format_double(acc); 5434d9b34d9Smrg DrawDisplay(); 5444d9b34d9Smrg dnum=acc; 5454d9b34d9Smrg } 5464d9b34d9Smrg } 5474d9b34d9Smrg else { /* op stack is empty, push op and num */ 5484d9b34d9Smrg PushOp(keynum); 5494d9b34d9Smrg PushNum(dnum); 550498372abSmrg } 551498372abSmrg} 5524d9b34d9Smrg 5534d9b34d9Smrg/* Two operand functions for rpn calc */ 5544d9b34d9Smrgvoid 5554d9b34d9Smrgtwof(int keynum) 5564d9b34d9Smrg{ 5574d9b34d9Smrg if (flagINV) { 5584d9b34d9Smrg flagINV=0; 5594d9b34d9Smrg DrawDisplay(); 5604d9b34d9Smrg } 5614d9b34d9Smrg if (!entered) 5624d9b34d9Smrg return; 5634d9b34d9Smrg if (entered==1) 5642256ab8cSmrg parse_double(&dnum); 5654d9b34d9Smrg acc = PopNum(); 5664d9b34d9Smrg switch(keynum) { 5674d9b34d9Smrg case kADD: acc += dnum; break; 5684d9b34d9Smrg case kSUB: acc -= dnum; break; 5694d9b34d9Smrg case kMUL: acc *= dnum; break; 5704d9b34d9Smrg case kDIV: acc /= dnum; break; 5714d9b34d9Smrg case kPOW: acc = pow(acc,dnum); break; 5722256ab8cSmrg case kXXY: PushNum(dnum); break; 5732256ab8cSmrg case kMOD: acc = (long)acc % (long)dnum; break; 5742256ab8cSmrg case kAND: acc = (long)acc & (long)dnum; break; 5752256ab8cSmrg case kOR: acc = (long)acc | (long)dnum; break; 5762256ab8cSmrg case kXOR: acc = (long)acc ^ (long)dnum; break; 5772256ab8cSmrg case kSHL: acc = (long)acc << (long)dnum; break; 5782256ab8cSmrg case kSHR: acc = (long)acc >> (long)dnum; break; 5794d9b34d9Smrg } 5802256ab8cSmrg 5812256ab8cSmrg format_double(acc); 5824d9b34d9Smrg DrawDisplay(); 5834d9b34d9Smrg clrdisp++; 5844d9b34d9Smrg Dpoint = exponent = 0; 5854d9b34d9Smrg entered = 2; 5864d9b34d9Smrg lift_enabled = 1; 5874d9b34d9Smrg dnum = acc; 5884d9b34d9Smrg} 5894d9b34d9Smrg 5904d9b34d9Smrgvoid 5914d9b34d9Smrgentrf(void) 5924d9b34d9Smrg{ 5934d9b34d9Smrg flagINV=0; 5944d9b34d9Smrg if (!entered) 5954d9b34d9Smrg return; 5964d9b34d9Smrg 5974d9b34d9Smrg clrdisp=CLR=1; 5984d9b34d9Smrg Dpoint=exponent=0; 5994d9b34d9Smrg 6004d9b34d9Smrg if (entered==1) 6012256ab8cSmrg parse_double(&dnum); 6024d9b34d9Smrg entered=2; 6034d9b34d9Smrg memop = kENTR; 6044d9b34d9Smrg PushNum(dnum); 6054d9b34d9Smrg lift_enabled = 0; 6064d9b34d9Smrg} 6074d9b34d9Smrg 6084d9b34d9Smrgvoid 6094d9b34d9Smrgequf(void) 6104d9b34d9Smrg{ 6114d9b34d9Smrg flagINV=0; 6124d9b34d9Smrg if (!entered) 6134d9b34d9Smrg return; 6144d9b34d9Smrg 6154d9b34d9Smrg clrdisp=CLR=1; 6164d9b34d9Smrg Dpoint=exponent=0; 6174d9b34d9Smrg 6184d9b34d9Smrg if (entered==1) 6192256ab8cSmrg parse_double(&dnum); 6204d9b34d9Smrg entered=2; 6214d9b34d9Smrg 6224d9b34d9Smrg PushNum(dnum); 6234d9b34d9Smrg 6244d9b34d9Smrg while (!isopempty()) { /* do all pending ops */ 6254d9b34d9Smrg dnum=PopNum(); 6264d9b34d9Smrg acc=PopNum(); 6274d9b34d9Smrg lastop=PopOp(); 6284d9b34d9Smrg switch (lastop) { 6294d9b34d9Smrg case kADD: acc += dnum; 6304d9b34d9Smrg break; 6314d9b34d9Smrg case kSUB: acc -= dnum; 6324d9b34d9Smrg break; 6334d9b34d9Smrg case kMUL: acc *= dnum; 6344d9b34d9Smrg break; 6354d9b34d9Smrg case kDIV: acc /= dnum; 6364d9b34d9Smrg break; 6374d9b34d9Smrg case kPOW: acc = pow(acc,dnum); 6384d9b34d9Smrg break; 6394d9b34d9Smrg case kLPAR: flagPAREN--; 6404d9b34d9Smrg PushNum(acc); 6414d9b34d9Smrg break; 6422256ab8cSmrg case kMOD: acc = (long)acc % (long)dnum; 6432256ab8cSmrg break; 6442256ab8cSmrg case kAND: acc = (long)acc & (long)dnum; 6452256ab8cSmrg break; 6462256ab8cSmrg case kOR: acc = (long)acc | (long)dnum; 6472256ab8cSmrg break; 6482256ab8cSmrg case kXOR: acc = (long)acc ^ (long)dnum; 6492256ab8cSmrg break; 6502256ab8cSmrg case kSHL: acc = (long)acc << (long)dnum; 6512256ab8cSmrg break; 6522256ab8cSmrg case kSHR: acc = (long)acc >> (long)dnum; 6532256ab8cSmrg break; 6544d9b34d9Smrg } 6554d9b34d9Smrg dnum=acc; 6564d9b34d9Smrg PushNum(dnum); 6574d9b34d9Smrg } 6584d9b34d9Smrg 6592256ab8cSmrg format_double(dnum); 6604d9b34d9Smrg DrawDisplay(); 6614d9b34d9Smrg} 662498372abSmrg 6634d9b34d9Smrgvoid 6644d9b34d9Smrglparf(void) 6654d9b34d9Smrg{ 6664d9b34d9Smrg flagINV=0; 6674d9b34d9Smrg PushOp(kLPAR); 6684d9b34d9Smrg flagPAREN++; 6694d9b34d9Smrg DrawDisplay(); 6704d9b34d9Smrg} 6714d9b34d9Smrg 6724d9b34d9Smrgvoid 6734d9b34d9Smrgrollf(void) 6744d9b34d9Smrg{ 6754d9b34d9Smrg if (!entered) 6764d9b34d9Smrg return; 6774d9b34d9Smrg if (entered==1) 6782256ab8cSmrg parse_double(&dnum); 6794d9b34d9Smrg entered = 2; 6804d9b34d9Smrg lift_enabled = 1; 6814d9b34d9Smrg RollNum(flagINV); 6824d9b34d9Smrg flagINV=0; 6834d9b34d9Smrg clrdisp++; 6842256ab8cSmrg format_double(dnum); 6854d9b34d9Smrg DrawDisplay(); 6864d9b34d9Smrg} 6874d9b34d9Smrg 6884d9b34d9Smrgvoid 6894d9b34d9Smrgrparf(void) 6904d9b34d9Smrg{ 6914d9b34d9Smrg flagINV=0; 6924d9b34d9Smrg if (!entered) 6934d9b34d9Smrg return; 6944d9b34d9Smrg 6954d9b34d9Smrg if (!flagPAREN) 6964d9b34d9Smrg return; 697498372abSmrg 6984d9b34d9Smrg clrdisp++; 6994d9b34d9Smrg Dpoint=exponent=0; 7004d9b34d9Smrg 7014d9b34d9Smrg if (entered==1) 7022256ab8cSmrg parse_double(&dnum); 7034d9b34d9Smrg entered=2; 7044d9b34d9Smrg 7054d9b34d9Smrg PushNum(dnum); 7064d9b34d9Smrg while (!isopempty() && (lastop=PopOp())!=kLPAR) { 7074d9b34d9Smrg /* do all pending ops, back to left paren */ 7084d9b34d9Smrg dnum=PopNum(); 7094d9b34d9Smrg acc=PopNum(); 7104d9b34d9Smrg switch (lastop) { 7114d9b34d9Smrg case kADD: acc += dnum; 7124d9b34d9Smrg break; 7134d9b34d9Smrg case kSUB: acc -= dnum; 7144d9b34d9Smrg break; 7154d9b34d9Smrg case kMUL: acc *= dnum; 7164d9b34d9Smrg break; 7174d9b34d9Smrg case kDIV: acc /= dnum; 7184d9b34d9Smrg break; 7194d9b34d9Smrg case kPOW: acc = pow(acc,dnum); 7204d9b34d9Smrg break; 7212256ab8cSmrg case kMOD: acc = (long)acc % (long)dnum; 7222256ab8cSmrg break; 7232256ab8cSmrg case kAND: acc = (long)acc & (long)dnum; 7242256ab8cSmrg break; 7252256ab8cSmrg case kOR: acc = (long)acc | (long)dnum; 7262256ab8cSmrg break; 7272256ab8cSmrg case kXOR: acc = (long)acc ^ (long)dnum; 7282256ab8cSmrg break; 7292256ab8cSmrg case kSHL: acc = (long)acc << (long)dnum; 7302256ab8cSmrg break; 7312256ab8cSmrg case kSHR: acc = (long)acc >> (long)dnum; 7322256ab8cSmrg break; 7334d9b34d9Smrg } 7344d9b34d9Smrg dnum=acc; 7354d9b34d9Smrg PushNum(dnum); 7364d9b34d9Smrg } 737fc5a3af9Smrg PopNum(); 7384d9b34d9Smrg flagPAREN--; 7394d9b34d9Smrg entered=2; 7402256ab8cSmrg format_double(dnum); 7414d9b34d9Smrg DrawDisplay(); 7424d9b34d9Smrg} 7434d9b34d9Smrg 7444d9b34d9Smrgvoid 7454d9b34d9Smrgdrgf(void) 7464d9b34d9Smrg{ 7474d9b34d9Smrg if (flagINV) { 7484d9b34d9Smrg if (entered==1) 7492256ab8cSmrg parse_double(&dnum); 7504d9b34d9Smrg switch (drgmode) { 75119d64aeeSmrg case DEG: dnum=dnum*M_PI/180.0; break; 75219d64aeeSmrg case RAD: dnum=dnum*200.0/M_PI; break; 7534d9b34d9Smrg case GRAD: dnum=dnum*90.0/100.0; break; 7544d9b34d9Smrg } 7554d9b34d9Smrg entered=2; 7564d9b34d9Smrg clrdisp=1; 7574d9b34d9Smrg flagINV=0; 7582256ab8cSmrg format_double(dnum); 7594d9b34d9Smrg } 760498372abSmrg 7614d9b34d9Smrg flagINV=0; 7624d9b34d9Smrg drgmode = (drgmode + 1) % 3; 7634d9b34d9Smrg switch (drgmode) { 76419d64aeeSmrg case DEG: drg2rad=M_PI / 180.0; 76519d64aeeSmrg rad2drg=180.0 / M_PI; 7664d9b34d9Smrg break; 7674d9b34d9Smrg case RAD: drg2rad=1.0; 7684d9b34d9Smrg rad2drg=1.0; 7694d9b34d9Smrg break; 77019d64aeeSmrg case GRAD: drg2rad=M_PI / 200.0; 77119d64aeeSmrg rad2drg=200.0 / M_PI; 7724d9b34d9Smrg break; 7734d9b34d9Smrg } 7744d9b34d9Smrg DrawDisplay(); 7754d9b34d9Smrg} 7764d9b34d9Smrg 7774d9b34d9Smrgvoid 7784d9b34d9Smrginvf(void) 7794d9b34d9Smrg{ 7804d9b34d9Smrg flagINV = ~flagINV; 7814d9b34d9Smrg DrawDisplay(); 7824d9b34d9Smrg} 7834d9b34d9Smrg 7844d9b34d9Smrgvoid 7854d9b34d9Smrgmemf(int keynum) 7864d9b34d9Smrg{ 7874d9b34d9Smrg memop = keynum; 7884d9b34d9Smrg if (entered==1) 7892256ab8cSmrg parse_double(&dnum); 7904d9b34d9Smrg entered = 2; 7914d9b34d9Smrg clrdisp++; 7924d9b34d9Smrg lift_enabled = 0; 7934d9b34d9Smrg} 7944d9b34d9Smrg 7954d9b34d9Smrgvoid 7964d9b34d9Smrgoneop(int keynum) 7974d9b34d9Smrg{ 7984d9b34d9Smrg int i,j; 7994d9b34d9Smrg double dtmp; 8004d9b34d9Smrg 8014d9b34d9Smrg if (entered==1) 8022256ab8cSmrg parse_double(&dnum); 8034d9b34d9Smrg entered = 2; 8044d9b34d9Smrg 8054d9b34d9Smrg switch (keynum) { /* do the actual math fn. */ 80619d64aeeSmrg case kE: if (rpn && memop != kENTR) PushNum(dnum); dnum=M_E; break; 80719d64aeeSmrg case kPI: if (rpn && memop != kENTR) PushNum(dnum); dnum=M_PI; break; 8084d9b34d9Smrg case kRECIP: dnum=1.0/dnum; break; 8090df20633Smrg case kSQR: flagINV = !flagINV; /* fall through */ 8104d9b34d9Smrg case kSQRT: if (flagINV) dnum=dnum*dnum; 8114d9b34d9Smrg else dnum=sqrt(dnum); 8124d9b34d9Smrg break; 8130df20633Smrg case k10X: flagINV = !flagINV; /* fall through */ 8144d9b34d9Smrg case kLOG: if (flagINV) dnum=pow(10.0,dnum); 8154d9b34d9Smrg else dnum=log10(dnum); 8164d9b34d9Smrg break; 8170df20633Smrg case kEXP: flagINV = !flagINV; /* fall through */ 8184d9b34d9Smrg case kLN: if (flagINV) dnum=exp(dnum); 8194d9b34d9Smrg else dnum=log(dnum); 8204d9b34d9Smrg break; 8214d9b34d9Smrg case kSIN: if (flagINV) dnum=asin(dnum)*rad2drg; 8224d9b34d9Smrg else dnum=sin(dnum*drg2rad); 8234d9b34d9Smrg break; 8244d9b34d9Smrg case kCOS: if (flagINV) dnum=acos(dnum)*rad2drg; 8254d9b34d9Smrg else dnum=cos(dnum*drg2rad); 8264d9b34d9Smrg break; 8274d9b34d9Smrg case kTAN: if (flagINV) dnum=atan(dnum)*rad2drg; 8284d9b34d9Smrg else dnum=tan(dnum*drg2rad); 8294d9b34d9Smrg break; 8304d9b34d9Smrg case kSTO: mem[0]=dnum; flagM=!(mem[0]==0.0); break; 8314d9b34d9Smrg case kRCL: if (rpn && lift_enabled) PushNum(dnum); 8324d9b34d9Smrg dnum=mem[0]; flagM=!(mem[0]==0.0); break; 8334d9b34d9Smrg case kSUM: mem[0]+=dnum; flagM=!(mem[0]==0.0); break; 8344d9b34d9Smrg case kEXC: dtmp=dnum; dnum=mem[0]; mem[0]=dtmp; 8354d9b34d9Smrg flagM=!(mem[0]==0.0); break; 8364d9b34d9Smrg case kFACT: if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) { 83719d64aeeSmrg strlcpy(dispstr, "error", sizeof(dispstr)); 8384d9b34d9Smrg entered=3; 8394d9b34d9Smrg break; 8404d9b34d9Smrg } 8418512f934Smrg dtmp = floor(dnum); i = dtmp; 842498372abSmrg for (j=1,dnum=1.0; j<=i; j++) 8434d9b34d9Smrg dnum*=(float) j; 8444d9b34d9Smrg break; 8452256ab8cSmrg case kNOT: dnum = ~(long)dnum; break; 8462256ab8cSmrg case kTRUNC: dnum = trunc(dnum); break; 8474d9b34d9Smrg } 848498372abSmrg 8494d9b34d9Smrg if (entered==3) { /* error */ 8504d9b34d9Smrg DrawDisplay(); 8514d9b34d9Smrg return; 8524d9b34d9Smrg } 8534d9b34d9Smrg 8544d9b34d9Smrg memop = keynum; 8554d9b34d9Smrg entered=2; 8564d9b34d9Smrg clrdisp=1; 8574d9b34d9Smrg flagINV=0; 8584d9b34d9Smrg lift_enabled = 1; 8592256ab8cSmrg format_double(dnum); 8604d9b34d9Smrg DrawDisplay(); 8614d9b34d9Smrg} 8624d9b34d9Smrg 8634d9b34d9Smrgvoid 8644d9b34d9Smrgofff(void) 8654d9b34d9Smrg{ 8664d9b34d9Smrg /* full reset */ 8674d9b34d9Smrg ResetCalc(); 8684d9b34d9Smrg entered=clrdisp=1; 8694d9b34d9Smrg lift_enabled = 0; 8704d9b34d9Smrg dnum=mem[0]=0.0; 8714d9b34d9Smrg if (rpn) 8720df20633Smrg for (int i=1; i < XCALC_MEMORY; i++) 8734d9b34d9Smrg mem[i]=0.0; 8744d9b34d9Smrg exponent=Dpoint=0; 8754d9b34d9Smrg DrawDisplay(); 8764d9b34d9Smrg} 8774d9b34d9Smrg 8784d9b34d9Smrg 8794d9b34d9Smrg#define STACKMAX 32 8804d9b34d9Smrgstatic int opstack[STACKMAX]; 8814d9b34d9Smrgstatic int opsp; 8824d9b34d9Smrgstatic double numstack[STACKMAX]; 8834d9b34d9Smrgstatic int numsp; 8844d9b34d9Smrg 8854d9b34d9Smrg 8864d9b34d9Smrg/*******/ 8874d9b34d9Smrgstatic void 8888512f934SmrgPushOp(int op) 8894d9b34d9Smrg/*******/ 8904d9b34d9Smrg{ 89119d64aeeSmrg if (opsp==STACKMAX) { 89219d64aeeSmrg strlcpy(dispstr, "stack error", sizeof(dispstr)); 89319d64aeeSmrg entered=3; 89419d64aeeSmrg } else 89519d64aeeSmrg opstack[opsp++]=op; 8964d9b34d9Smrg} 8974d9b34d9Smrg 8984d9b34d9Smrg/*******/ 8994d9b34d9Smrgstatic int 9004d9b34d9SmrgPopOp(void) 9014d9b34d9Smrg/*******/ 9024d9b34d9Smrg{ 9034d9b34d9Smrg if (opsp==0) { 90419d64aeeSmrg strlcpy(dispstr, "stack error", sizeof(dispstr)); 9054d9b34d9Smrg entered=3; 9064d9b34d9Smrg return(kNOP); 9074d9b34d9Smrg } else 9084d9b34d9Smrg return(opstack[--opsp]); 9094d9b34d9Smrg} 9104d9b34d9Smrg 9114d9b34d9Smrg/*******/ 9124d9b34d9Smrgstatic int 9134d9b34d9Smrgisopempty(void) 9144d9b34d9Smrg/*******/ 9154d9b34d9Smrg{ 9164d9b34d9Smrg return( opsp ? 0 : 1 ); 9174d9b34d9Smrg} 9184d9b34d9Smrg 9194d9b34d9Smrg#ifdef DEBUG 9204d9b34d9Smrgstatic void 9218512f934Smrgshowstack(char *string) 9224d9b34d9Smrg{ 9234d9b34d9Smrg fprintf(stderr, "%s: %lf %lf %lf\n", string, numstack[0], numstack[1], 9244d9b34d9Smrg numstack[2]); 9254d9b34d9Smrg} 9264d9b34d9Smrg#endif 9274d9b34d9Smrg 9284d9b34d9Smrg/*******/ 9294d9b34d9Smrgstatic void 9308512f934SmrgPushNum(double num) 9314d9b34d9Smrg/*******/ 9324d9b34d9Smrg{ 9334d9b34d9Smrg if (rpn) { 9344d9b34d9Smrg numstack[2] = numstack[1]; 9354d9b34d9Smrg numstack[1] = numstack[0]; 9364d9b34d9Smrg numstack[0] = num; 9374d9b34d9Smrg return; 9384d9b34d9Smrg } 9394d9b34d9Smrg if (numsp==STACKMAX) { 94019d64aeeSmrg strlcpy(dispstr, "stack error", sizeof(dispstr)); 9414d9b34d9Smrg entered=3; 9424d9b34d9Smrg } else 9434d9b34d9Smrg numstack[numsp++]=num; 9444d9b34d9Smrg} 9454d9b34d9Smrg 9464d9b34d9Smrg/*******/ 9474d9b34d9Smrgstatic double 9484d9b34d9SmrgPopNum(void) 9494d9b34d9Smrg/*******/ 9504d9b34d9Smrg{ 9514d9b34d9Smrg if (rpn) { 9524d9b34d9Smrg double tmp = numstack[0]; 9534d9b34d9Smrg numstack[0] = numstack[1]; 9544d9b34d9Smrg numstack[1] = numstack[2]; 9554d9b34d9Smrg return(tmp); 9564d9b34d9Smrg } 9574d9b34d9Smrg if (numsp==0) { 95819d64aeeSmrg strlcpy(dispstr, "stack error", sizeof(dispstr)); 9594d9b34d9Smrg entered=3; 9604d9b34d9Smrg return 0.0; 9614d9b34d9Smrg } else 9624d9b34d9Smrg return(numstack[--numsp]); 9634d9b34d9Smrg} 9644d9b34d9Smrg 9654d9b34d9Smrg/*******/ 9664d9b34d9Smrgstatic void 9674d9b34d9SmrgRollNum(int dir) 9684d9b34d9Smrg/*******/ 9694d9b34d9Smrg{ 9704d9b34d9Smrg double tmp; 9714d9b34d9Smrg 9724d9b34d9Smrg if (dir) { /* roll up */ 9734d9b34d9Smrg tmp = dnum; 9744d9b34d9Smrg dnum = numstack[2]; 9754d9b34d9Smrg numstack[2] = numstack[1]; 9764d9b34d9Smrg numstack[1] = numstack[0]; 9774d9b34d9Smrg numstack[0] = tmp; 9784d9b34d9Smrg } else { /* roll down */ 9794d9b34d9Smrg tmp = dnum; 9804d9b34d9Smrg dnum = numstack[0]; 9814d9b34d9Smrg numstack[0] = numstack[1]; 9824d9b34d9Smrg numstack[1] = numstack[2]; 9834d9b34d9Smrg numstack[2] = tmp; 9844d9b34d9Smrg } 9854d9b34d9Smrg} 9864d9b34d9Smrg 9874d9b34d9Smrg 9884d9b34d9Smrg/*******/ 9894d9b34d9Smrgstatic void 9904d9b34d9SmrgClearStacks(void) 9914d9b34d9Smrg/*******/ 9924d9b34d9Smrg{ 9934d9b34d9Smrg if (rpn) 9944d9b34d9Smrg numstack[0] = numstack[1] = numstack[2] = 0.; 9954d9b34d9Smrg opsp=numsp=0; 9964d9b34d9Smrg} 9974d9b34d9Smrg 9984d9b34d9Smrg 9994d9b34d9Smrg/*******/ 10004d9b34d9Smrgstatic int 10018512f934Smrgpriority(int op) 10024d9b34d9Smrg/*******/ 10034d9b34d9Smrg{ 10044d9b34d9Smrg switch (op) { 10052256ab8cSmrg case kPOW: return(6); 10064d9b34d9Smrg case kMUL: 10072256ab8cSmrg case kDIV: 10082256ab8cSmrg case kMOD: return(5); 10094d9b34d9Smrg case kADD: 10102256ab8cSmrg case kSUB: return(4); 10112256ab8cSmrg case kSHL: 10122256ab8cSmrg case kSHR: return(3); 10132256ab8cSmrg case kAND: return(2); 10142256ab8cSmrg case kXOR: return(1); 10152256ab8cSmrg case kOR: return(0); 10162256ab8cSmrg } 10174d9b34d9Smrg return 0; 10184d9b34d9Smrg} 10194d9b34d9Smrg 10204d9b34d9Smrg 10214d9b34d9Smrg/********/ 10224d9b34d9Smrgvoid 10234d9b34d9SmrgResetCalc(void) 10244d9b34d9Smrg/********/ 10254d9b34d9Smrg{ 10264d9b34d9Smrg flagM=flagINV=flagPAREN=0; drgmode=DEG; 10272256ab8cSmrg numbase=(!numbase ? 10 : numbase); 10284d9b34d9Smrg setflag(XCalc_MEMORY, False); 10294d9b34d9Smrg setflag(XCalc_INVERSE, False); 10304d9b34d9Smrg setflag(XCalc_PAREN, False); 10314d9b34d9Smrg setflag(XCalc_RADIAN, False); 10324d9b34d9Smrg setflag(XCalc_GRADAM, False); 10334d9b34d9Smrg setflag(XCalc_DEGREE, True); 10342256ab8cSmrg setflag(XCalc_HEX, False); 10352256ab8cSmrg setflag(XCalc_DEC, True); 10362256ab8cSmrg setflag(XCalc_OCT, False); 103719d64aeeSmrg strlcpy(dispstr, "0", sizeof(dispstr)); 10384d9b34d9Smrg draw(dispstr); 10394d9b34d9Smrg ClearStacks(); 104019d64aeeSmrg drg2rad=M_PI/180.0; 104119d64aeeSmrg rad2drg=180.0/M_PI; 10424d9b34d9Smrg} 1043