math.c revision 498372ab
1/* 2 * math.c - mathematics functions for a hand calculator under X 3 * 4 * Author: John H. Bradley, University of Pennsylvania 5 * (bradley@cis.upenn.edu) 6 * March, 1987 7 * 8 * RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena 9 * 10 * Modified to be a client of the Xt toolkit and the Athena widget set by 11 * Donna Converse, MIT X Consortium. This is all that remains of the 12 * original calculator, and it still needs to be rewritten. The HP 13 * functionality should be separated from the TI functionality. 14 * Beware the HP functions: there are still errors here. 15 * 16 * Geoffrey Coram fixed most of the HP mode bugs. 17 */ 18 19#include "xcalc.h" 20 21#ifdef _CRAY /* kludge around Cray STDC compiler */ 22double (*log_p)() = log; 23#define log ((*log_p)) 24double (*exp_p)() = exp; 25#define exp ((*exp_p)) 26double (*sqrt_p)() = sqrt; 27#define sqrt ((*sqrt_p)) 28double (*log10_p)() = log10; 29#define log10 ((*log10_p)) 30double (*atan2_p)() = atan2; 31#define atan2 ((*atan2_p)) 32double (*asin_p)() = asin; 33#define asin ((*asin_p)) 34double (*acos_p)() = acos; 35#define acos ((*acos_p)) 36double (*atan_p)() = atan; 37#define atan ((*atan_p)) 38double (*sin_p)() = sin; 39#define sin ((*sin_p)) 40double (*cos_p)() = cos; 41#define cos ((*cos_p)) 42double (*tan_p)() = tan; 43#define tan ((*tan_p)) 44double (*pow_p)() = pow; 45#define pow ((*pow_p)) 46#endif /* _CRAY */ 47 48#ifndef PI /* sometimes defined in math.h */ 49#define PI 3.14159265358979 50#endif 51#define E 2.71828182845904 52#define MAXDISP 11 53#define DEG 0 /* DRG mode. used for trig calculations */ 54#define RAD 1 55#define GRAD 2 56#define min(a,b) ((a) < (b) ? (a) : (b)) 57#define max(a,b) ((a) > (b) ? (a) : (b)) 58#define True 1 59#define False 0 60 61#ifndef IEEE 62jmp_buf env; 63#endif 64 65 66/* This section is all of the state machine that implements the calculator 67 * functions. Much of it is shared between the infix and rpn modes. 68 */ 69 70static int flagINV, flagPAREN, flagM, drgmode; /* display flags */ 71 72static double drg2rad=PI/180.0; /* Conversion factors for trig funcs */ 73static double rad2drg=180.0/PI; 74static int entered=1; /* true if display contains a valid number. 75 if==2, then use 'dnum', rather than the string 76 stored in the display. (for accuracy) 77 if==3, then error occurred, only CLR & AC work */ 78/* entered seems to be overloaded - dmc */ 79static int lift_enabled = 0; /* for rpn mode only */ 80 81static int CLR =0; /* CLR clears display. if 1, clears acc, also */ 82static int Dpoint=0; /* to prevent using decimal pt twice in a # */ 83static int clrdisp=1; /* if true clears display before entering # */ 84static int lastop =kCLR; 85static int memop =kCLR; 86static int exponent=0; 87static double acc =0.0; 88static double dnum=0.0; 89#define XCALC_MEMORY 10 90static double mem[XCALC_MEMORY] = { 0.0 }; 91 92static void DrawDisplay(void); 93static void PushOp(int op); 94static int PopOp(void); 95static int isopempty(void); 96#ifdef DEBUG 97static void showstack(char *string); 98#endif 99static void PushNum(double num); 100static double PopNum(void); 101static void RollNum(int dir); 102static void ClearStacks(void); 103static int priority(int op); 104 105/* 106 * The following is to deal with the unfortunate assumption that if errno 107 * is non-zero then an error has occurred. On some systems (e.g. Ultrix), 108 * sscanf will call lower level routines that will set errno. 109 */ 110 111static void 112parse_double (const char *src, const char *fmt, double *dp) 113{ 114 int olderrno = errno; 115 116 (void) sscanf (src, fmt, dp); 117 errno = olderrno; 118 return; 119} 120 121 122/*********************************/ 123int pre_op(int keynum) 124{ 125 if (keynum==-1) return(0); 126 127 errno = 0; /* for non-IEEE machines */ 128 129 if ( (entered==3) && !(keynum==kCLR || keynum==kOFF)) { 130 if (rpn) { 131 clrdisp++; 132 } else { 133 ringbell(); 134 return(1); /* the intent was probably not to do the operation */ 135 } 136 } 137 138 if (keynum != kCLR) CLR=0; 139 return(0); 140} 141 142#ifndef IEEE 143 144/* cannot assign result of setjmp under ANSI C, use global instead */ 145static volatile int SignalKind; 146 147void fail_op(void) 148{ 149 if (SignalKind == SIGFPE) 150 strcpy(dispstr, "math error"); 151 else if (SignalKind == SIGILL) 152 strcpy(dispstr, "illegal operand"); 153 154 entered=3; 155 DrawDisplay(); 156 return; 157} 158 159/*ARGSUSED*/ 160signal_t fperr(int sig) 161{ 162#if defined(SYSV) || defined(SVR4) || defined(linux) 163 signal(SIGFPE, fperr); 164#endif 165 SignalKind = sig; 166 longjmp(env,1); 167} 168 169/* for VAX BSD4.3 */ 170/*ARGSUSED*/ 171signal_t illerr(int sig) 172{ 173 /* not reset when caught? */ 174 signal(SIGILL, illerr); 175 176 SignalKind = sig; 177 longjmp(env,1); 178} 179 180#endif /* not IEEE */ 181 182 183void post_op(void) 184{ 185#ifdef DEBUG 186 showstack("\0"); 187#endif 188#ifndef IEEE 189 if (errno) { 190 strcpy(dispstr,"error"); 191 DrawDisplay(); 192 entered=3; 193 errno=0; 194 } 195#endif 196} 197/*-------------------------------------------------------------------------*/ 198static void 199DrawDisplay(void) 200{ 201 if ((int) strlen(dispstr) > 12) { /* strip out some decimal digits */ 202 char tmp[32]; 203 char *estr = index(dispstr,'e'); /* search for exponent part */ 204 if (!estr) dispstr[12]='\0'; /* no exp, just trunc. */ 205 else { 206 if ((int) strlen(estr) <= 4) 207 sprintf(tmp,"%.8s",dispstr); /* leftmost 8 chars */ 208 else 209 sprintf(tmp,"%.7s",dispstr); /* leftmost 7 chars */ 210 strcat (tmp,estr); /* plus exponent */ 211 strcpy (dispstr,tmp); 212 } 213 } 214 draw(dispstr); 215 setflag(XCalc_MEMORY, (flagM)); 216 setflag(XCalc_INVERSE, (flagINV)); 217 setflag(XCalc_DEGREE, (drgmode==DEG)); 218 setflag(XCalc_RADIAN, (drgmode==RAD)); 219 setflag(XCalc_GRADAM, (drgmode==GRAD)); 220 setflag(XCalc_PAREN, (flagPAREN)); 221} 222 223/*-------------------------------------------------------------------------*/ 224void 225numeric(int keynum) 226{ 227 char st[2]; 228 int cell = 0; 229 230 flagINV=0; 231 232 if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) { 233 switch (keynum) { 234 case kONE: cell = 1; break; 235 case kTWO: cell = 2; break; 236 case kTHREE: cell = 3; break; 237 case kFOUR: cell = 4; break; 238 case kFIVE: cell = 5; break; 239 case kSIX: cell = 6; break; 240 case kSEVEN: cell = 7; break; 241 case kEIGHT: cell = 8; break; 242 case kNINE: cell = 9; break; 243 case kZERO: cell = 0; break; 244 } 245 switch (memop) { 246 case kSTO: 247 mem[cell] = dnum; 248 lift_enabled = 1; 249 entered = 2; 250 clrdisp++; 251 break; 252 case kRCL: 253 PushNum(dnum); 254 dnum = mem[cell]; 255 sprintf(dispstr, "%.8g", dnum); 256 lift_enabled = 1; 257 entered = 1; 258 clrdisp++; 259 break; 260 case kSUM: 261 mem[cell] += dnum; 262 lift_enabled = 1; 263 entered = 2; 264 clrdisp++; 265 break; 266 } 267 memop = kCLR; 268 DrawDisplay(); 269 return; 270 } 271 272 if (clrdisp) { 273 dispstr[0]='\0'; 274 exponent=Dpoint=0; 275/* if (rpn && entered==2) 276 PushNum(dnum); 277 */ 278 if (rpn & lift_enabled) 279 PushNum(dnum); 280 } 281 if ((int) strlen(dispstr) >= MAXDISP) 282 return; 283 284 switch (keynum){ 285 case kONE: st[0] = '1'; break; 286 case kTWO: st[0] = '2'; break; 287 case kTHREE: st[0] = '3'; break; 288 case kFOUR: st[0] = '4'; break; 289 case kFIVE: st[0] = '5'; break; 290 case kSIX: st[0] = '6'; break; 291 case kSEVEN: st[0] = '7'; break; 292 case kEIGHT: st[0] = '8'; break; 293 case kNINE: st[0] = '9'; break; 294 case kZERO: st[0] = '0'; break; 295 } 296 st[1] = '\0'; 297 strcat(dispstr,st); 298 299 DrawDisplay(); 300 if (clrdisp && keynum != kZERO) 301 clrdisp=0; /*no leading 0s*/ 302 memop = keynum; 303 entered=1; 304 lift_enabled = 0; 305} 306 307void 308bkspf(void) 309{ 310 311 lift_enabled = 0; 312 313 if (! flagINV) 314 { 315 if (entered!=1) { 316 clearf(); 317 return; 318 } 319 if (clrdisp) 320 return; 321 if ((int) strlen(dispstr) > 0) { 322#ifndef X_LOCALE 323 const char *dp = localeconv()->decimal_point; 324 size_t dp_len = strlen(dp); 325 size_t ds_len = strlen(dispstr); 326 if (ds_len >= dp_len && strcmp(dispstr + ds_len - dp_len, dp) == 0) 327 Dpoint=0; 328#else 329 if (dispstr[strlen(dispstr)-1] == '.') 330 Dpoint=0; 331#endif 332 dispstr[strlen(dispstr)-1] = 0; 333 } 334 if (strlen(dispstr) == 0) { 335 strcat(dispstr, "0"); 336 clrdisp++; 337 } 338 } 339 else 340 { 341 strcpy(dispstr, "0"); 342 dnum = 0.0; 343 clrdisp++; 344 flagINV = 0; 345 } 346 DrawDisplay(); 347} 348 349void 350decf(void) 351{ 352 flagINV=0; 353 if (clrdisp) { 354 if (rpn && lift_enabled) 355 PushNum(dnum); 356 strcpy(dispstr,"0"); 357 } 358 if (!Dpoint) { 359#ifndef X_LOCALE 360 strcat(dispstr, localeconv()->decimal_point); 361#else 362 strcat(dispstr, "."); 363#endif 364 DrawDisplay(); 365 Dpoint++; 366 } 367 clrdisp=0; 368 entered=1; 369} 370 371void 372eef(void) 373{ 374 flagINV=0; 375 if (clrdisp) { 376 if (rpn && lift_enabled) 377 PushNum(dnum); 378 strcpy(dispstr, rpn ? "1" : "0"); 379 } 380 if (!exponent) { 381 strcat(dispstr,"E+"); 382 DrawDisplay(); 383 exponent=strlen(dispstr)-1; /* where the '-' goes */ 384 } 385 clrdisp=0; 386 entered=1; 387} 388 389void 390clearf(void) 391{ 392 flagINV=0; 393 if (CLR && !rpn) { /* clear all */ 394 ClearStacks(); 395 flagPAREN=0; 396 } 397 CLR++; 398 exponent=Dpoint=0; 399 clrdisp=1; 400 entered=1; 401 strcpy(dispstr,"0"); 402 DrawDisplay(); 403} 404 405void 406negf(void) 407{ 408 flagINV=0; 409 if (exponent) { /* neg the exponent */ 410 if (dispstr[exponent]=='-') 411 dispstr[exponent]='+'; 412 else 413 dispstr[exponent]='-'; 414 DrawDisplay(); 415 return; 416 } 417 418 if (strcmp("0",dispstr)==0) 419 return; /* don't neg a zero */ 420 if (dispstr[0]=='-') /* already neg-ed */ 421 strcpy(dispstr,dispstr+1); /* move str left once */ 422 else { /* not neg-ed. add a '-' */ 423 char tmp[32]; 424 sprintf(tmp,"-%s",dispstr); 425 strcpy(dispstr,tmp); 426 } 427 if (entered==2) 428 dnum = -1.0 * dnum; 429 DrawDisplay(); 430} 431 432/* Two operand functions for infix calc */ 433void 434twoop(int keynum) 435{ 436 if (flagINV) { 437 flagINV=0; 438 DrawDisplay(); 439 } 440 441 if (!entered) { /* something like "5+*" */ 442 if (!isopempty()) 443 (void) PopOp(); /* replace the prev op */ 444 PushOp(keynum); /* with the new one */ 445 return; 446 } 447 448 if (entered==1) 449 parse_double(dispstr,"%lf",&dnum); 450 451 clrdisp=CLR=1; 452 entered=Dpoint=exponent=0; 453 454 if (!isopempty()) { /* there was a previous op */ 455 lastop=PopOp(); /* get it */ 456 457 if (lastop==kLPAR) { /* put it back */ 458 PushOp(kLPAR); 459 PushOp(keynum); 460 PushNum(dnum); 461 return; 462 } 463 464 /* now, if the current op (keynum) is of 465 higher priority than the lastop, the current 466 op and number are just pushed on top 467 Priorities: (Y^X) > *,/ > +,- */ 468 469 if (priority(keynum) > priority(lastop)) { 470 PushNum(dnum); 471 PushOp(lastop); 472 PushOp(keynum); 473 } else { /* execute lastop on lastnum and dnum, push 474 result and current op on stack */ 475 acc=PopNum(); 476 switch (lastop) { /* perform the operation */ 477 case kADD: acc += dnum; break; 478 case kSUB: acc -= dnum; break; 479 case kMUL: acc *= dnum; break; 480 case kDIV: acc /= dnum; break; 481 case kPOW: acc = pow(acc,dnum); break; 482 } 483 PushNum(acc); 484 PushOp(keynum); 485 sprintf(dispstr,"%.8g",acc); 486 DrawDisplay(); 487 dnum=acc; 488 } 489 } 490 else { /* op stack is empty, push op and num */ 491 PushOp(keynum); 492 PushNum(dnum); 493 } 494} 495 496/* Two operand functions for rpn calc */ 497void 498twof(int keynum) 499{ 500 if (flagINV) { 501 flagINV=0; 502 DrawDisplay(); 503 } 504 if (!entered) 505 return; 506 if (entered==1) 507 parse_double(dispstr, "%lf", &dnum); 508 acc = PopNum(); 509 switch(keynum) { 510 case kADD: acc += dnum; break; 511 case kSUB: acc -= dnum; break; 512 case kMUL: acc *= dnum; break; 513 case kDIV: acc /= dnum; break; 514 case kPOW: acc = pow(acc,dnum); break; 515 case kXXY: PushNum(dnum); 516 } 517 sprintf(dispstr, "%.8g", acc); 518 DrawDisplay(); 519 clrdisp++; 520 Dpoint = exponent = 0; 521 entered = 2; 522 lift_enabled = 1; 523 dnum = acc; 524} 525 526void 527entrf(void) 528{ 529 flagINV=0; 530 if (!entered) 531 return; 532 533 clrdisp=CLR=1; 534 Dpoint=exponent=0; 535 536 if (entered==1) 537 parse_double(dispstr,"%lf",&dnum); 538 entered=2; 539 memop = kENTR; 540 PushNum(dnum); 541 lift_enabled = 0; 542} 543 544void 545equf(void) 546{ 547 flagINV=0; 548 if (!entered) 549 return; 550 551 clrdisp=CLR=1; 552 Dpoint=exponent=0; 553 554 if (entered==1) 555 parse_double(dispstr,"%lf",&dnum); 556 entered=2; 557 558 PushNum(dnum); 559 560 while (!isopempty()) { /* do all pending ops */ 561 dnum=PopNum(); 562 acc=PopNum(); 563 lastop=PopOp(); 564 switch (lastop) { 565 case kADD: acc += dnum; 566 break; 567 case kSUB: acc -= dnum; 568 break; 569 case kMUL: acc *= dnum; 570 break; 571 case kDIV: acc /= dnum; 572 break; 573 case kPOW: acc = pow(acc,dnum); 574 break; 575 case kLPAR: flagPAREN--; 576 PushNum(acc); 577 break; 578 } 579 dnum=acc; 580 PushNum(dnum); 581 } 582 583 sprintf(dispstr,"%.8g",dnum); 584 DrawDisplay(); 585} 586 587void 588lparf(void) 589{ 590 flagINV=0; 591 PushOp(kLPAR); 592 flagPAREN++; 593 DrawDisplay(); 594} 595 596void 597rollf(void) 598{ 599 if (!entered) 600 return; 601 if (entered==1) 602 parse_double(dispstr, "%lf", &dnum); 603 entered = 2; 604 lift_enabled = 1; 605 RollNum(flagINV); 606 flagINV=0; 607 clrdisp++; 608 sprintf(dispstr, "%.8g", dnum); 609 DrawDisplay(); 610} 611 612void 613rparf(void) 614{ 615 flagINV=0; 616 if (!entered) 617 return; 618 619 if (!flagPAREN) 620 return; 621 622 clrdisp++; 623 Dpoint=exponent=0; 624 625 if (entered==1) 626 parse_double(dispstr,"%lf",&dnum); 627 entered=2; 628 629 PushNum(dnum); 630 while (!isopempty() && (lastop=PopOp())!=kLPAR) { 631 /* do all pending ops, back to left paren */ 632 dnum=PopNum(); 633 acc=PopNum(); 634 switch (lastop) { 635 case kADD: acc += dnum; 636 break; 637 case kSUB: acc -= dnum; 638 break; 639 case kMUL: acc *= dnum; 640 break; 641 case kDIV: acc /= dnum; 642 break; 643 case kPOW: acc = pow(acc,dnum); 644 break; 645 } 646 dnum=acc; 647 PushNum(dnum); 648 } 649 (void) PopNum(); 650 flagPAREN--; 651 entered=2; 652 sprintf(dispstr,"%.8g",dnum); 653 DrawDisplay(); 654} 655 656void 657drgf(void) 658{ 659 if (flagINV) { 660 if (entered==1) 661 parse_double(dispstr,"%lf",&dnum); 662 switch (drgmode) { 663 case DEG: dnum=dnum*PI/180.0; break; 664 case RAD: dnum=dnum*200.0/PI; break; 665 case GRAD: dnum=dnum*90.0/100.0; break; 666 } 667 entered=2; 668 clrdisp=1; 669 flagINV=0; 670 sprintf(dispstr,"%.8g",dnum); 671 } 672 673 flagINV=0; 674 drgmode = (drgmode + 1) % 3; 675 switch (drgmode) { 676 case DEG: drg2rad=PI / 180.0; 677 rad2drg=180.0 / PI; 678 break; 679 case RAD: drg2rad=1.0; 680 rad2drg=1.0; 681 break; 682 case GRAD: drg2rad=PI / 200.0; 683 rad2drg=200.0 / PI; 684 break; 685 } 686 DrawDisplay(); 687} 688 689void 690invf(void) 691{ 692 flagINV = ~flagINV; 693 DrawDisplay(); 694} 695 696void 697memf(int keynum) 698{ 699 memop = keynum; 700 if (entered==1) 701 parse_double(dispstr,"%lf",&dnum); 702 entered = 2; 703 clrdisp++; 704 lift_enabled = 0; 705} 706 707void 708oneop(int keynum) 709{ 710 int i,j; 711 double dtmp; 712 713 if (entered==1) 714 parse_double(dispstr,"%lf",&dnum); 715 entered = 2; 716 717 switch (keynum) { /* do the actual math fn. */ 718 case kE: if (rpn && memop != kENTR) PushNum(dnum); dnum=E; break; 719 case kPI: if (rpn && memop != kENTR) PushNum(dnum); dnum=PI; break; 720 case kRECIP: dnum=1.0/dnum; break; 721 case kSQR: flagINV = !flagINV; /* fall through to */ 722 case kSQRT: if (flagINV) dnum=dnum*dnum; 723 else dnum=sqrt(dnum); 724 break; 725 case k10X: flagINV = !flagINV; /* fall through to */ 726 case kLOG: if (flagINV) dnum=pow(10.0,dnum); 727 else dnum=log10(dnum); 728 break; 729 case kEXP: flagINV = !flagINV; /* fall through to */ 730 case kLN: if (flagINV) dnum=exp(dnum); 731 else dnum=log(dnum); 732 break; 733 case kSIN: if (flagINV) dnum=asin(dnum)*rad2drg; 734 else dnum=sin(dnum*drg2rad); 735 break; 736 case kCOS: if (flagINV) dnum=acos(dnum)*rad2drg; 737 else dnum=cos(dnum*drg2rad); 738 break; 739 case kTAN: if (flagINV) dnum=atan(dnum)*rad2drg; 740 else dnum=tan(dnum*drg2rad); 741 break; 742 case kSTO: mem[0]=dnum; flagM=!(mem[0]==0.0); break; 743 case kRCL: if (rpn && lift_enabled) PushNum(dnum); 744 dnum=mem[0]; flagM=!(mem[0]==0.0); break; 745 case kSUM: mem[0]+=dnum; flagM=!(mem[0]==0.0); break; 746 case kEXC: dtmp=dnum; dnum=mem[0]; mem[0]=dtmp; 747 flagM=!(mem[0]==0.0); break; 748 case kFACT: if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) { 749 strcpy(dispstr,"error"); 750 entered=3; 751 break; 752 } 753 dtmp = floor(dnum); i = dtmp; 754 for (j=1,dnum=1.0; j<=i; j++) 755 dnum*=(float) j; 756 break; 757 } 758 759 if (entered==3) { /* error */ 760 DrawDisplay(); 761 return; 762 } 763 764 memop = keynum; 765 entered=2; 766 clrdisp=1; 767 flagINV=0; 768 lift_enabled = 1; 769 sprintf(dispstr,"%.8g",dnum); 770 DrawDisplay(); 771} 772 773void 774offf(void) 775{ 776 /* full reset */ 777 int i; 778 ResetCalc(); 779 entered=clrdisp=1; 780 lift_enabled = 0; 781 dnum=mem[0]=0.0; 782 if (rpn) 783 for (i=1; i < XCALC_MEMORY; i++) 784 mem[i]=0.0; 785 exponent=Dpoint=0; 786 DrawDisplay(); 787} 788 789 790#define STACKMAX 32 791static int opstack[STACKMAX]; 792static int opsp; 793static double numstack[STACKMAX]; 794static int numsp; 795 796 797/*******/ 798static void 799PushOp(int op) 800/*******/ 801{ 802 if (opsp==STACKMAX) {strcpy(dispstr,"stack error"); entered=3;} 803 else opstack[opsp++]=op; 804} 805 806/*******/ 807static int 808PopOp(void) 809/*******/ 810{ 811 if (opsp==0) { 812 strcpy(dispstr,"stack error"); 813 entered=3; 814 return(kNOP); 815 } else 816 return(opstack[--opsp]); 817} 818 819/*******/ 820static int 821isopempty(void) 822/*******/ 823{ 824 return( opsp ? 0 : 1 ); 825} 826 827#ifdef DEBUG 828static void 829showstack(char *string) 830{ 831 fprintf(stderr, "%s: %lf %lf %lf\n", string, numstack[0], numstack[1], 832 numstack[2]); 833} 834#endif 835 836/*******/ 837static void 838PushNum(double num) 839/*******/ 840{ 841 if (rpn) { 842 numstack[2] = numstack[1]; 843 numstack[1] = numstack[0]; 844 numstack[0] = num; 845 return; 846 } 847 if (numsp==STACKMAX) { 848 strcpy(dispstr,"stack error"); 849 entered=3; 850 } else 851 numstack[numsp++]=num; 852} 853 854/*******/ 855static double 856PopNum(void) 857/*******/ 858{ 859 if (rpn) { 860 double tmp = numstack[0]; 861 numstack[0] = numstack[1]; 862 numstack[1] = numstack[2]; 863 return(tmp); 864 } 865 if (numsp==0) { 866 strcpy(dispstr,"stack error"); 867 entered=3; 868 return 0.0; 869 } else 870 return(numstack[--numsp]); 871} 872 873/*******/ 874static void 875RollNum(int dir) 876/*******/ 877{ 878 double tmp; 879 880 if (dir) { /* roll up */ 881 tmp = dnum; 882 dnum = numstack[2]; 883 numstack[2] = numstack[1]; 884 numstack[1] = numstack[0]; 885 numstack[0] = tmp; 886 } else { /* roll down */ 887 tmp = dnum; 888 dnum = numstack[0]; 889 numstack[0] = numstack[1]; 890 numstack[1] = numstack[2]; 891 numstack[2] = tmp; 892 } 893} 894 895 896/*******/ 897static void 898ClearStacks(void) 899/*******/ 900{ 901 if (rpn) 902 numstack[0] = numstack[1] = numstack[2] = 0.; 903 opsp=numsp=0; 904} 905 906 907/*******/ 908static int 909priority(int op) 910/*******/ 911{ 912 switch (op) { 913 case kPOW: return(2); 914 case kMUL: 915 case kDIV: return(1); 916 case kADD: 917 case kSUB: return(0); 918 } 919 return 0; 920} 921 922 923/********/ 924void 925ResetCalc(void) 926/********/ 927{ 928 flagM=flagINV=flagPAREN=0; drgmode=DEG; 929 setflag(XCalc_MEMORY, False); 930 setflag(XCalc_INVERSE, False); 931 setflag(XCalc_PAREN, False); 932 setflag(XCalc_RADIAN, False); 933 setflag(XCalc_GRADAM, False); 934 setflag(XCalc_DEGREE, True); 935 strcpy(dispstr,"0"); 936 draw(dispstr); 937 ClearStacks(); 938 drg2rad=PI/180.0; 939 rad2drg=180.0/PI; 940} 941