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