00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <config.h>
00033 #include <assert.h>
00034 #include <stdio.h>
00035 #include <errno.h>
00036 #include <limits.h>
00037 #include <math.h>
00038 #include <signal.h>
00039 #include <klocale.h>
00040 #include <kmessagebox.h>
00041 #include <knotifyclient.h>
00042
00043 #include "kcalc.h"
00044
00045
00046
00047
00048
00049
00050
00051 #ifdef HAVE_LONG_DOUBLE
00052 #undef HAVE_LONG_DOUBLE
00053 #endif
00054
00055 #ifndef HAVE_FUNC_ISINF
00056 #ifdef HAVE_IEEEFP_H
00057 #include <ieeefp.h>
00058 #else
00059 #include <math.h>
00060 #endif
00061
00062 int isinf(double x) { return !finite(x) && x==x; }
00063 #endif
00064
00065 extern QPtrList<CALCAMNT> temp_stack;
00066 last_input_type last_input;
00067 char display_str[DSP_SIZE+1];
00068
00069 stack_ptr top_of_stack = NULL;
00070 stack_ptr top_type_stack[2] = { NULL, NULL };
00071 int stack_next, stack_last;
00072 stack_item process_stack[STACK_SIZE];
00073
00074 int inverse = FALSE;
00075 int precedence_base = 0;
00076 num_base current_base = NB_DECIMAL;
00077 int input_limit = 0;
00078 int input_count = 0;
00079
00080
00081 item_contents display_data;
00082
00083 int display_size = DEC_SIZE;
00084
00085 int hyp_mode = 0;
00086 int angle_mode = ANG_DEGREE;
00087 int refresh_display;
00088 int display_error = 0;
00089 int decimal_point = 0;
00090 int percent_mode = 0;
00091 bool eestate = false;
00092
00093 CALCAMNT pi;
00094 CALCAMNT memory_num = 0.0;
00095
00096 int precedence[14] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 6 };
00097
00098 int adjust_op[14][3] = {
00099 {FUNC_NULL, FUNC_NULL, FUNC_NULL},
00100 {FUNC_OR, FUNC_OR, FUNC_XOR },
00101 {FUNC_XOR, FUNC_XOR, FUNC_XOR },
00102 {FUNC_AND, FUNC_AND, FUNC_AND },
00103 {FUNC_LSH, FUNC_LSH, FUNC_RSH },
00104 {FUNC_RSH, FUNC_RSH, FUNC_RSH },
00105 {FUNC_ADD, FUNC_ADD, FUNC_ADD },
00106 {FUNC_SUBTRACT, FUNC_SUBTRACT, FUNC_SUBTRACT},
00107 {FUNC_MULTIPLY, FUNC_MULTIPLY, FUNC_MULTIPLY},
00108 {FUNC_DIVIDE, FUNC_DIVIDE, FUNC_DIVIDE},
00109 {FUNC_MOD, FUNC_MOD, FUNC_INTDIV },
00110 {FUNC_POWER, FUNC_POWER, FUNC_PWR_ROOT},
00111 {FUNC_PWR_ROOT, FUNC_PWR_ROOT, FUNC_PWR_ROOT},
00112 {FUNC_INTDIV, FUNC_INTDIV, FUNC_INTDIV},
00113 };
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 Arith Arith_ops[14] = { NULL,
00134 ExecOr,
00135 ExecXor,
00136 ExecAnd,
00137 ExecLsh,
00138 ExecRsh,
00139 ExecAdd, ExecSubtract,
00140 ExecMultiply,
00141 ExecDivide, ExecMod,
00142 ExecPower, ExecPwrRoot,
00143 ExecIntDiv
00144 };
00145
00146 Prcnt Prcnt_ops[14] = { NULL,
00147 NULL,
00148 NULL,
00149 NULL,
00150 NULL,
00151 NULL,
00152 ExecAddSubP, ExecAddSubP,
00153 ExecMultiplyP,
00154 ExecDivideP, ExecDivideP,
00155 ExecPowerP, ExecPwrRootP,
00156 ExecDivideP
00157 };
00158
00159
00160 void QtCalculator::InitializeCalculator(void) {
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 display_data.s_item_type = ITEM_AMOUNT;
00172 display_data.s_item_data.item_amount = 0.0;
00173 display_data.s_item_data.item_func_data.item_function = 0;
00174 display_data.s_item_data.item_func_data.item_precedence = 0;
00175
00176 void fpe_handler(int fpe_parm);
00177 struct sigaction fpe_trap;
00178
00179 fpe_trap.sa_handler = &fpe_handler;
00180 #ifdef SA_RESTART
00181 fpe_trap.sa_flags = SA_RESTART;
00182 #endif
00183
00184 sigaction(SIGFPE, &fpe_trap, NULL);
00185
00186 RefreshCalculator();
00187 pi = ASIN(1.0) * 2L;
00188 }
00189
00190 void fpe_handler(int fpe_parm)
00191 {
00192 (void) fpe_parm;
00193
00194 display_error = 1;
00195 DISPLAY_AMOUNT = 0L;
00196
00197 }
00198
00199 void QtCalculator::setData( const QRect& _range, const char *_sheet )
00200 {
00201 sheet_range = _range;
00202 sheet_name = _sheet;
00203 }
00204
00205 void QtCalculator::setValue( double _value )
00206 {
00207 last_input = DIGIT;
00208 DISPLAY_AMOUNT = _value;
00209 decimal_point = 0;
00210 refresh_display = 1;
00211 input_count = 0;
00212
00213 UpdateDisplay();
00214 }
00215
00216 void QtCalculator::setLabel( const char *_text )
00217 {
00218 last_input = DIGIT;
00219 DISPLAY_AMOUNT = 0L;
00220 decimal_point = 0;
00221 refresh_display = 0;
00222 input_count = 0;
00223
00224 calc_display->setText( _text );
00225 }
00226
00227 void QtCalculator::RefreshCalculator(void)
00228 {
00229 InitStack();
00230 display_error = 0;
00231 DISPLAY_AMOUNT = 0L;
00232 inverse = FALSE;
00233 UpdateDisplay();
00234 last_input = DIGIT;
00235
00236 input_count = 0;
00237 decimal_point = 0;
00238 }
00239
00240 void QtCalculator::EnterDigit(int data)
00241 {
00242
00243 if(eestate){
00244
00245 QString string;
00246 string.setNum(data);
00247 strcat(display_str, string.latin1());
00248 DISPLAY_AMOUNT = (CALCAMNT) strtod(display_str,0);
00249 UpdateDisplay();
00250 return;
00251
00252 }
00253
00254 last_input = DIGIT;
00255 if (refresh_display) {
00256 DISPLAY_AMOUNT = 0L;
00257 decimal_point = 0;
00258 refresh_display = 0;
00259 input_count = 0;
00260 }
00261
00262 if (!(input_limit && input_count >= input_limit))
00263 if (DISPLAY_AMOUNT < 0)
00264 DISPLAY_AMOUNT = decimal_point ?
00265 DISPLAY_AMOUNT - ((CALCAMNT)data /
00266 POW((float)current_base, decimal_point++)) :
00267 (current_base * DISPLAY_AMOUNT) - data;
00268 else
00269 DISPLAY_AMOUNT = decimal_point ?
00270 DISPLAY_AMOUNT + ((CALCAMNT)data /
00271 POW((float)current_base, decimal_point++)) :
00272 (current_base * DISPLAY_AMOUNT) + data;
00273
00274 if (decimal_point){
00275 input_count ++;
00276
00277 #ifdef MYDEBUG
00278 printf("EnterDigit() inc dec.point:%d\n",input_count);
00279 #endif
00280
00281 }
00282 UpdateDisplay();
00283 }
00284
00285 void QtCalculator::button0()
00286 {
00287 EnterDigit(0);
00288 }
00289
00290 void QtCalculator::button1()
00291 {
00292 EnterDigit(1);
00293 }
00294
00295 void QtCalculator::button2()
00296 {
00297 if (current_base == NB_BINARY)
00298 return;
00299 EnterDigit(2);
00300 }
00301
00302 void QtCalculator::button3()
00303 {
00304 if (current_base == NB_BINARY)
00305 return;
00306 EnterDigit(3);
00307 }
00308
00309 void QtCalculator::button4()
00310 {
00311 if (current_base == NB_BINARY)
00312 return;
00313 EnterDigit(4);
00314 }
00315
00316 void QtCalculator::button5()
00317 {
00318 if (current_base == NB_BINARY)
00319 return;
00320 EnterDigit(5);
00321 }
00322
00323 void QtCalculator::button6()
00324 {
00325 if (current_base == NB_BINARY)
00326 return;
00327 EnterDigit(6);
00328 }
00329
00330 void QtCalculator::button7()
00331 {
00332 if (current_base == NB_BINARY)
00333 return;
00334 EnterDigit(7);
00335 }
00336
00337 void QtCalculator::button8()
00338 {
00339 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL))
00340 return;
00341 EnterDigit(8);
00342 }
00343
00344 void QtCalculator::button9()
00345 {
00346 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL))
00347 return;
00348 EnterDigit(9);
00349 }
00350
00351
00352 void QtCalculator::buttonA()
00353 {
00354 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00355 || (current_base == NB_DECIMAL))
00356 return;
00357 EnterDigit(10);
00358 }
00359
00360
00361 void QtCalculator::buttonB()
00362 {
00363 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00364 || (current_base == NB_DECIMAL))
00365 return;
00366 EnterDigit(11);
00367 }
00368
00369
00370 void QtCalculator::buttonC()
00371 {
00372 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00373 || (current_base == NB_DECIMAL))
00374 return;
00375 EnterDigit(12);
00376 }
00377
00378
00379 void QtCalculator::buttonD()
00380 {
00381 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00382 || (current_base == NB_DECIMAL))
00383 return;
00384 EnterDigit(13);
00385 }
00386
00387
00388 void QtCalculator::buttonE()
00389 {
00390 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00391 || (current_base == NB_DECIMAL))
00392 return;
00393 EnterDigit(14);
00394 }
00395
00396 void QtCalculator::buttonF()
00397 {
00398 if ((current_base == NB_BINARY) || (current_base == NB_OCTAL)
00399 || (current_base == NB_DECIMAL))
00400 return;
00401 EnterDigit(15);
00402 }
00403
00404
00405
00406 void QtCalculator::EnterDecimal()
00407 {
00408
00409 if(eestate){
00410 KNotifyClient::beep();
00411 return;
00412 }
00413
00414 decimal_point = 1;
00415 if (refresh_display) {
00416 DISPLAY_AMOUNT = 0L;
00417 refresh_display = 0;
00418 input_count = 0;
00419 }
00420
00421 if (last_input == DIGIT && !strpbrk( display_str,".")){
00422
00423
00424
00425
00426 calc_display->setText(strcat(display_str, "."));
00427 }
00428 else {
00429
00430
00431
00432
00433 DISPLAY_AMOUNT = 0L;
00434 refresh_display = 0;
00435
00436
00437 strcpy(display_str, "0.");
00438 calc_display->setText(display_str);
00439 }
00440 }
00441
00442
00443 void QtCalculator::Or()
00444 {
00445 eestate = false;
00446 if (inverse){
00447 EnterStackFunction(2);
00448 inverse = FALSE;
00449 }
00450 else {
00451 EnterStackFunction(1);
00452 }
00453 last_input = OPERATION;
00454 }
00455
00456 void QtCalculator::And()
00457 {
00458 eestate = false;
00459 last_input = OPERATION;
00460 EnterStackFunction(3);
00461 }
00462
00463
00464 void QtCalculator::Shift()
00465 {
00466 eestate = false;
00467 last_input = OPERATION;
00468 if (inverse){
00469 EnterStackFunction(5);
00470 inverse = FALSE;
00471 }
00472 else {
00473 EnterStackFunction(4);
00474 }
00475
00476 }
00477
00478 void QtCalculator::Plus()
00479 {
00480 eestate = false;
00481 last_input = OPERATION;
00482 EnterStackFunction(6);
00483 }
00484
00485 void QtCalculator::Minus()
00486 {
00487 eestate = false;
00488 last_input = OPERATION;
00489 EnterStackFunction(7);
00490
00491 }
00492
00493 void QtCalculator::Multiply()
00494 {
00495 eestate = false;
00496 last_input = OPERATION;
00497 EnterStackFunction(8);
00498 }
00499
00500 void QtCalculator::Divide()
00501 {
00502 eestate = false;
00503 last_input = OPERATION;
00504 EnterStackFunction(9);
00505 }
00506
00507 void QtCalculator::Mod()
00508 {
00509 eestate = false;
00510 last_input = OPERATION;
00511 if (inverse){
00512 EnterStackFunction(13);
00513 inverse = FALSE;
00514 }
00515 else {
00516 EnterStackFunction(10);
00517 }
00518 }
00519
00520 void QtCalculator::Power()
00521 {
00522 eestate = false;
00523 last_input = OPERATION;
00524 if (inverse){
00525 EnterStackFunction(12);
00526 inverse = FALSE;
00527 }
00528 else {
00529 EnterStackFunction(11);
00530 }
00531
00532 }
00533
00534
00535
00536 void QtCalculator::EnterStackFunction(int data)
00537 {
00538 item_contents new_item;
00539 int new_precedence;
00540 int dummy;
00541
00542 dummy = 0;
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 data = adjust_op[data][dummy];
00556
00557
00558 PushStack(&display_data);
00559
00560 new_item.s_item_type = ITEM_FUNCTION;
00561 new_item.s_item_data.item_func_data.item_function = data;
00562 new_item.s_item_data.item_func_data.item_precedence =
00563 new_precedence = precedence[data] + precedence_base;
00564
00565 refresh_display = 1;
00566 if (UpdateStack(new_precedence))
00567 UpdateDisplay();
00568 PushStack(&new_item);
00569 }
00570
00571 void QtCalculator::EnterNegate()
00572 {
00573
00574 if(eestate){
00575 QString string;
00576 string = display_str;
00577 int pos;
00578 pos = string.findRev('e',-1,false);
00579 if(pos == -1)
00580 return;
00581
00582 if(display_str[pos+1] == '+')
00583 display_str[pos+1] = '-';
00584 else{
00585 if(display_str[pos+1] == '-')
00586 display_str[pos+1] = '+';
00587 else{
00588 string.insert(pos +1,'-');
00589 strncpy(display_str,string.latin1(),DSP_SIZE);
00590 }
00591 }
00592 DISPLAY_AMOUNT = (CALCAMNT)strtod(display_str,0);
00593 UpdateDisplay();
00594 }
00595 else{
00596
00597 if (DISPLAY_AMOUNT != 0) {
00598 DISPLAY_AMOUNT *= -1;
00599 UpdateDisplay();
00600 }
00601 }
00602 last_input = DIGIT;
00603 }
00604
00605 void QtCalculator::EnterOpenParen()
00606 {
00607 eestate = false;
00608 last_input = OPERATION;
00609 precedence_base += PRECEDENCE_INCR;
00610 refresh_display = 1;
00611
00612 }
00613
00614 void QtCalculator::EnterCloseParen()
00615 {
00616 eestate = false;
00617 last_input = OPERATION;
00618 PushStack(&display_data);
00619 refresh_display = 1;
00620 if (UpdateStack(precedence_base))
00621 UpdateDisplay();
00622 if ((precedence_base -= PRECEDENCE_INCR) < 0)
00623 precedence_base = 0;
00624
00625 }
00626
00627 void QtCalculator::EnterRecip()
00628 {
00629 eestate = false;
00630 last_input = OPERATION;
00631 DISPLAY_AMOUNT = 1 / DISPLAY_AMOUNT;
00632 refresh_display = 1;
00633 UpdateDisplay();
00634 }
00635
00636 void QtCalculator::EnterInt()
00637 {
00638 eestate = false;
00639 CALCAMNT work_amount1, work_amount2;
00640
00641 last_input = OPERATION;
00642 if (!inverse){
00643 work_amount2 = MODF(DISPLAY_AMOUNT, &work_amount1);
00644 DISPLAY_AMOUNT = work_amount2 ;
00645 }
00646 else {
00647 DISPLAY_AMOUNT = work_amount1;
00648 inverse = FALSE;
00649 }
00650
00651 refresh_display = 1;
00652 UpdateDisplay();
00653
00654 }
00655
00656 void QtCalculator::EnterFactorial()
00657 {
00658 eestate = false;
00659 CALCAMNT work_amount1, work_amount2;
00660 int incr;
00661
00662 MODF(DISPLAY_AMOUNT, &work_amount1);
00663
00664 incr = work_amount1 < 0 ? -1 : 1;
00665 work_amount2 = work_amount1 - incr;
00666 while (work_amount1 != 0 && work_amount2 != 0 && !display_error) {
00667 work_amount1 *= work_amount2;
00668 work_amount2 -= incr;
00669 if(isinf(work_amount1)) {
00670 display_error=1;
00671 break;
00672 }
00673 }
00674
00675 if( work_amount1 == 0.0)
00676 work_amount1 = 1.0;
00677
00678 DISPLAY_AMOUNT = work_amount1;
00679 refresh_display = 1;
00680 last_input = OPERATION;
00681 UpdateDisplay();
00682
00683 }
00684
00685 void QtCalculator::EnterSquare()
00686 {
00687 eestate = false;
00688 if (!inverse){
00689 DISPLAY_AMOUNT *= DISPLAY_AMOUNT;
00690 }
00691 else if (DISPLAY_AMOUNT < 0)
00692 display_error = 1;
00693 else
00694 DISPLAY_AMOUNT = SQRT(DISPLAY_AMOUNT);
00695 refresh_display = 1;
00696 inverse = FALSE;
00697 last_input = OPERATION;
00698 UpdateDisplay();
00699
00700 }
00701
00702 void QtCalculator::EnterNotCmp()
00703 {
00704 eestate = false;
00705 CALCAMNT boh_work_d;
00706 long boh_work;
00707
00708 MODF(DISPLAY_AMOUNT, &boh_work_d);
00709 if (FABS(boh_work_d) > LONG_MAX)
00710 display_error = 1;
00711 else {
00712 boh_work = (long int) boh_work_d;
00713 DISPLAY_AMOUNT = ~boh_work;
00714 }
00715 refresh_display = 1;
00716 last_input = OPERATION;
00717 UpdateDisplay();
00718
00719 }
00720
00721 void QtCalculator::EnterHyp()
00722 {
00723
00724 switch(kcalcdefaults.style){
00725 case 2:
00726 case 1:{
00727 if ( !sheet_name.isEmpty() )
00728 useData();
00729
00730 if(!inverse){
00731 eestate = false;
00732 DISPLAY_AMOUNT = stats.count();
00733 last_input = OPERATION;
00734 refresh_display = 1;
00735 UpdateDisplay();
00736 }
00737 else{
00738 inverse = false;
00739 eestate = false;
00740 DISPLAY_AMOUNT = stats.sum();
00741 last_input = OPERATION;
00742 refresh_display = 1;
00743 UpdateDisplay();
00744 }
00745
00746 break;
00747 }
00748
00749 case 0: {
00750
00751 hyp_mode = !hyp_mode;
00752
00753 if (hyp_mode){
00754 statusHYPLabel->setText("HYP");
00755 }
00756 else{
00757 statusHYPLabel->setText("");
00758 }
00759 break;
00760 }
00761 }
00762 }
00763
00764
00765 void QtCalculator::ExecSin(){
00766
00767 switch(kcalcdefaults.style){
00768
00769 case 0:{
00770
00771 ComputeSin();
00772 break;
00773 }
00774
00775 case 1:{
00776 if ( !sheet_name.isEmpty() )
00777 useData();
00778
00779 ComputeMean();
00780 break;
00781 }
00782
00783 case 2:{
00784 if ( !sheet_name.isEmpty() )
00785 useData();
00786
00787 ComputeMin();
00788 break;
00789 }
00790
00791 }
00792
00793 }
00794
00795 void QtCalculator::ComputeSum()
00796 {
00797 inverse = false;
00798 eestate = false;
00799 DISPLAY_AMOUNT = stats.sum();
00800 if (stats.error())
00801 display_error = 1;
00802
00803 refresh_display = 1;
00804 last_input = OPERATION;
00805 UpdateDisplay();
00806 }
00807
00808 void QtCalculator::ComputeMul()
00809 {
00810 inverse = false;
00811 eestate = false;
00812 DISPLAY_AMOUNT = stats.mul();
00813 if (stats.error())
00814 display_error = 1;
00815
00816 refresh_display = 1;
00817 last_input = OPERATION;
00818 UpdateDisplay();
00819 }
00820
00821 void QtCalculator::ComputeMin()
00822 {
00823 inverse = false;
00824 eestate = false;
00825 DISPLAY_AMOUNT = stats.min();
00826 if (stats.error())
00827 display_error = 1;
00828
00829 refresh_display = 1;
00830 last_input = OPERATION;
00831 UpdateDisplay();
00832 }
00833
00834 void QtCalculator::ComputeMax()
00835 {
00836 inverse = false;
00837 eestate = false;
00838 DISPLAY_AMOUNT = stats.max();
00839 if (stats.error())
00840 display_error = 1;
00841
00842 refresh_display = 1;
00843 last_input = OPERATION;
00844 UpdateDisplay();
00845 }
00846
00847 void QtCalculator::ComputeMean(){
00848
00849 if(!inverse){
00850 eestate = false;
00851 DISPLAY_AMOUNT = stats.mean();
00852 if (stats.error())
00853 display_error = 1;
00854
00855 refresh_display = 1;
00856 last_input = OPERATION;
00857 UpdateDisplay();
00858 }
00859 else{
00860 inverse = false;
00861 eestate = false;
00862 DISPLAY_AMOUNT = stats.sum_of_squares();
00863 if (stats.error())
00864 display_error = 1;
00865 refresh_display = 1;
00866 last_input = OPERATION;
00867 UpdateDisplay();
00868
00869 }
00870
00871 }
00872
00873 void QtCalculator::ComputeSin()
00874 {
00875 CALCAMNT work_amount;
00876 eestate = false;
00877 work_amount = DISPLAY_AMOUNT;
00878
00879 if (hyp_mode){
00880
00881 if (!inverse){
00882 DISPLAY_AMOUNT = SINH( work_amount);
00883 }
00884 else {
00885 DISPLAY_AMOUNT = ASINH( work_amount);
00886 if (errno == EDOM || errno == ERANGE)
00887 display_error = 1;
00888 inverse = FALSE;
00889 }
00890 }
00891 else {
00892
00893 if (!inverse){
00894
00895 switch (angle_mode) {
00896 case ANG_DEGREE:
00897 work_amount = DEG2RAD(DISPLAY_AMOUNT);
00898 break;
00899 case ANG_GRADIENT:
00900 work_amount = GRA2RAD(DISPLAY_AMOUNT);
00901 break;
00902 case ANG_RADIAN:
00903 work_amount = DISPLAY_AMOUNT;
00904 break;
00905 }
00906 DISPLAY_AMOUNT = SIN( work_amount);
00907 }
00908 else {
00909
00910 DISPLAY_AMOUNT = ASIN(work_amount);
00911 switch (angle_mode) {
00912 case ANG_DEGREE:
00913 work_amount = RAD2DEG(DISPLAY_AMOUNT);
00914 break;
00915 case ANG_GRADIENT:
00916 work_amount = RAD2GRA(DISPLAY_AMOUNT);
00917 break;
00918 case ANG_RADIAN:
00919 work_amount = DISPLAY_AMOUNT;
00920 break;
00921 }
00922 DISPLAY_AMOUNT = work_amount;
00923 if (errno == EDOM || errno == ERANGE)
00924 display_error = 1;
00925 inverse = FALSE;
00926 }
00927 }
00928
00929
00930
00931 if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO)
00932 DISPLAY_AMOUNT=0;
00933 refresh_display = 1;
00934 last_input = OPERATION;
00935 UpdateDisplay();
00936
00937 }
00938
00939 void QtCalculator::ExecCos(){
00940
00941 switch(kcalcdefaults.style){
00942
00943 case 0:{
00944
00945 ComputeCos();
00946 break;
00947 }
00948
00949 case 1:{
00950 if ( !sheet_name.isEmpty() )
00951 useData();
00952
00953 ComputeStd();
00954 break;
00955 }
00956
00957 case 2:{
00958 if ( !sheet_name.isEmpty() )
00959 useData();
00960
00961 ComputeMax();
00962 break;
00963 }
00964
00965 }
00966
00967 }
00968
00969 void QtCalculator::ComputeStd(){
00970
00971 if(!inverse){
00972 inverse = false;
00973 eestate = false;
00974 DISPLAY_AMOUNT = stats.std();
00975
00976 if (stats.error()){
00977 display_error = 1;
00978 }
00979
00980 refresh_display = 1;
00981 last_input = OPERATION;
00982 UpdateDisplay();
00983 }
00984 else{
00985
00986 inverse = false;
00987 eestate = false;
00988 DISPLAY_AMOUNT = stats.sample_std();
00989
00990 if (stats.error())
00991 display_error = 1;
00992
00993 refresh_display = 1;
00994 last_input = OPERATION;
00995 UpdateDisplay();
00996
00997
00998
00999 }
01000
01001 }
01002
01003 void QtCalculator::ComputeCos()
01004 {
01005 CALCAMNT work_amount;
01006 eestate = false;
01007 work_amount = DISPLAY_AMOUNT;
01008
01009 if (hyp_mode){
01010
01011 if (!inverse){
01012 DISPLAY_AMOUNT = COSH( work_amount);
01013 }
01014 else {
01015 DISPLAY_AMOUNT = ACOSH( work_amount);
01016 if (errno == EDOM || errno == ERANGE)
01017 display_error = 1;
01018 inverse = FALSE;
01019 }
01020 }
01021 else {
01022
01023 if (!inverse){
01024
01025 switch (angle_mode) {
01026 case ANG_DEGREE:
01027 work_amount = DEG2RAD(DISPLAY_AMOUNT);
01028 break;
01029 case ANG_GRADIENT:
01030 work_amount = GRA2RAD(DISPLAY_AMOUNT);
01031 break;
01032 case ANG_RADIAN:
01033 work_amount = DISPLAY_AMOUNT;
01034 break;
01035 }
01036 DISPLAY_AMOUNT = COS( work_amount);
01037 }
01038 else {
01039
01040 DISPLAY_AMOUNT = ACOS(work_amount);
01041 switch (angle_mode) {
01042 case ANG_DEGREE:
01043 work_amount = RAD2DEG(DISPLAY_AMOUNT);
01044 break;
01045 case ANG_GRADIENT:
01046 work_amount = RAD2GRA(DISPLAY_AMOUNT);
01047 break;
01048 case ANG_RADIAN:
01049 work_amount = DISPLAY_AMOUNT;
01050 break;
01051 }
01052
01053 DISPLAY_AMOUNT = work_amount;
01054
01055 if (errno == EDOM || errno == ERANGE)
01056 display_error = 1;
01057 inverse = FALSE;
01058 }
01059 }
01060
01061
01062
01063
01064 if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO)
01065 DISPLAY_AMOUNT=0;
01066 refresh_display = 1;
01067 last_input = OPERATION;
01068 UpdateDisplay();
01069
01070 }
01071
01072 void QtCalculator::ExecTan(){
01073
01074 switch(kcalcdefaults.style){
01075
01076 case 0:{
01077
01078 ComputeTan();
01079 break;
01080 }
01081
01082 case 2:
01083 case 1:{
01084
01085 if ( !sheet_name.isEmpty() )
01086 useData();
01087
01088 ComputeMedean();
01089 break;
01090 }
01091
01092 }
01093
01094 }
01095
01096 void QtCalculator::ComputeMedean(){
01097
01098 if(!inverse){
01099 inverse = false;
01100 eestate = false;
01101 DISPLAY_AMOUNT = stats.median();
01102
01103 if (stats.error()){
01104 display_error = 1;
01105 }
01106
01107 refresh_display = 1;
01108 last_input = OPERATION;
01109 UpdateDisplay();
01110 }
01111 else{
01112
01113 inverse = false;
01114 eestate = false;
01115 DISPLAY_AMOUNT = stats.median();
01116
01117 if (stats.error())
01118 display_error = 1;
01119
01120 refresh_display = 1;
01121 last_input = OPERATION;
01122 UpdateDisplay();
01123
01124 }
01125 }
01126
01127
01128 void QtCalculator::ComputeTan()
01129 {
01130 CALCAMNT work_amount;
01131 eestate = false;
01132 work_amount = DISPLAY_AMOUNT;
01133
01134 if (hyp_mode){
01135
01136 if (!inverse){
01137 DISPLAY_AMOUNT = TANH( work_amount);
01138 }
01139 else {
01140 DISPLAY_AMOUNT = ATANH( work_amount);
01141 if (errno == EDOM || errno == ERANGE)
01142 display_error = 1;
01143 inverse = FALSE;
01144 }
01145 }
01146 else {
01147
01148 if (!inverse){
01149
01150 switch (angle_mode) {
01151 case ANG_DEGREE:
01152 work_amount = DEG2RAD(DISPLAY_AMOUNT);
01153 break;
01154 case ANG_GRADIENT:
01155 work_amount = GRA2RAD(DISPLAY_AMOUNT);
01156 break;
01157 case ANG_RADIAN:
01158 work_amount = DISPLAY_AMOUNT;
01159 break;
01160 }
01161 DISPLAY_AMOUNT = TAN( work_amount);
01162 if (errno == EDOM || errno == ERANGE)
01163 display_error = 1;
01164 }
01165 else {
01166
01167 DISPLAY_AMOUNT = ATAN(work_amount);
01168 switch (angle_mode) {
01169 case ANG_DEGREE:
01170 work_amount = RAD2DEG(DISPLAY_AMOUNT);
01171 break;
01172 case ANG_GRADIENT:
01173 work_amount = RAD2GRA(DISPLAY_AMOUNT);
01174 break;
01175 case ANG_RADIAN:
01176 work_amount = DISPLAY_AMOUNT;
01177 break;
01178 }
01179
01180 DISPLAY_AMOUNT = work_amount;
01181
01182 if (errno == EDOM || errno == ERANGE)
01183 display_error = 1;
01184 inverse = FALSE;
01185 }
01186 }
01187
01188
01189
01190 if (DISPLAY_AMOUNT < POS_ZERO && DISPLAY_AMOUNT > NEG_ZERO)
01191 DISPLAY_AMOUNT=0;
01192 refresh_display = 1;
01193 last_input = OPERATION;
01194 UpdateDisplay();
01195
01196 }
01197
01198
01199 void QtCalculator::EnterPercent()
01200 {
01201 eestate = false;
01202 last_input = OPERATION;
01203 percent_mode = 1;
01204 EnterEqual();
01205 percent_mode = 0;
01206
01207 }
01208
01209 void QtCalculator::EnterLogr()
01210 {
01211
01212 switch(kcalcdefaults.style){
01213 case 2:
01214 {
01215 if ( !sheet_name.isEmpty() )
01216 useData();
01217
01218 ComputeSum();
01219 break;
01220 }
01221 case 1:{
01222
01223 if ( !sheet_name.isEmpty() )
01224 useData();
01225
01226 if(!inverse){
01227 eestate = false;
01228 stats.enterData(DISPLAY_AMOUNT);
01229 last_input = OPERATION;
01230 refresh_display = 1;
01231 DISPLAY_AMOUNT = stats.count();
01232 UpdateDisplay();
01233 }
01234 else{
01235 inverse = false;
01236 last_input = OPERATION;
01237 refresh_display = 1;
01238 stats.clearLast();
01239 setStatusLabel("Last stat item erased");
01240 DISPLAY_AMOUNT = stats.count();
01241 UpdateDisplay();
01242
01243 }
01244
01245 break;
01246 }
01247 case 0:{
01248
01249 eestate = false;
01250 last_input = OPERATION;
01251
01252 if (!inverse) {
01253 if (DISPLAY_AMOUNT <= 0)
01254 display_error = 1;
01255 else
01256 DISPLAY_AMOUNT = LOG_TEN(DISPLAY_AMOUNT);
01257 refresh_display = 1;
01258 UpdateDisplay();
01259 } else if (inverse) {
01260 DISPLAY_AMOUNT = POW(10, DISPLAY_AMOUNT);
01261 refresh_display = 1;
01262 inverse = FALSE;
01263 UpdateDisplay();
01264 }
01265 break;
01266 }
01267 }
01268 }
01269
01270 void QtCalculator::EnterLogn()
01271 {
01272
01273 switch(kcalcdefaults.style){
01274 case 2:{
01275
01276 if ( !sheet_name.isEmpty() )
01277 useData();
01278
01279 ComputeMul();
01280
01281 break;
01282 }
01283 case 1:{
01284
01285 if ( !sheet_name.isEmpty() )
01286 useData();
01287
01288 if(!inverse){
01289
01290 stats.clearAll();
01291 setStatusLabel(i18n("Stat mem cleared"));
01292
01293 }
01294 else{
01295 inverse = false;
01296 UpdateDisplay();
01297 }
01298
01299 break;
01300 }
01301 case 0:{
01302 eestate = false;
01303 last_input = OPERATION;
01304 if (!inverse) {
01305 if (DISPLAY_AMOUNT <= 0)
01306 display_error = 1;
01307 else
01308 DISPLAY_AMOUNT = LOG(DISPLAY_AMOUNT);
01309 refresh_display = 1;
01310 UpdateDisplay();
01311 } else if (inverse) {
01312 DISPLAY_AMOUNT = EXP(DISPLAY_AMOUNT);
01313 refresh_display = 1;
01314 inverse =FALSE;
01315 UpdateDisplay();
01316 }
01317 break;
01318 }
01319 }
01320
01321 }
01322
01323
01324 void QtCalculator::base_selected(int number){
01325
01326 switch(number){
01327 case 0:
01328 SetHex();
01329 break;
01330 case 1:
01331 SetDec();
01332 break;
01333 case 2:
01334 SetOct();
01335 break;
01336 case 3:
01337 SetBin();
01338 break;
01339 default:
01340 SetDec();
01341 }
01342 }
01343
01344
01345 void QtCalculator::angle_selected(int number){
01346
01347 switch(number){
01348 case 0:
01349 SetDeg();
01350 break;
01351 case 1:
01352 SetRad();
01353 break;
01354 case 2:
01355 SetGra();
01356 break;
01357 default:
01358 SetRad();
01359 }
01360 }
01361
01362 void QtCalculator::SetInverse(){
01363
01364 inverse = ! inverse;
01365 if (inverse){
01366 statusINVLabel->setText("INV");
01367 }
01368 else{
01369 statusINVLabel->setText("NORM");
01370 }
01371 }
01372
01373
01374 void QtCalculator::SetDeg() {
01375 angle_mode = ANG_DEGREE;
01376 }
01377
01378 void QtCalculator::SetGra() {
01379 angle_mode = ANG_GRADIENT;
01380 }
01381
01382 void QtCalculator::SetRad() {
01383 angle_mode = ANG_RADIAN;
01384
01385 }
01386
01387 void QtCalculator::SetHex() {
01388
01389
01390
01391
01392 current_base = NB_HEX;
01393 display_size = BOH_SIZE;
01394 decimal_point = 0;
01395 input_limit = 8;
01396
01397 UpdateDisplay();
01398 }
01399
01400 void QtCalculator::SetOct() {
01401
01402
01403
01404
01405 current_base = NB_OCTAL;
01406 display_size = BOH_SIZE;
01407 decimal_point = 0;
01408 input_limit = 11;
01409
01410 UpdateDisplay();
01411 }
01412
01413 void QtCalculator::SetBin() {
01414
01415
01416
01417
01418 current_base = NB_BINARY;
01419 display_size = BOH_SIZE;
01420 decimal_point = 0;
01421 input_limit = 16;
01422
01423 UpdateDisplay();
01424 }
01425
01426 void QtCalculator::SetDec()
01427 {
01428
01429
01430
01431
01432 current_base = NB_DECIMAL;
01433 display_size = DEC_SIZE;
01434 input_limit = 0;
01435
01436
01437 UpdateDisplay();
01438 }
01439
01440
01441 void QtCalculator::EE()
01442 {
01443 if(inverse){
01444 DISPLAY_AMOUNT = pi;
01445 inverse = FALSE;
01446 UpdateDisplay();
01447 }
01448 else{
01449 if(eestate == true)
01450 eestate = false;
01451 else{
01452 eestate = true;
01453 strcat(display_str,"e");
01454 }
01455
01456 UpdateDisplay();
01457 }
01458
01459 }
01460
01461 void QtCalculator::MR()
01462 {
01463 eestate = false;
01464 last_input = OPERATION;
01465 DISPLAY_AMOUNT = memory_num;
01466 refresh_display = 1;
01467 UpdateDisplay();
01468
01469 }
01470
01471 void QtCalculator::Mplusminus()
01472 {
01473
01474 eestate = false;
01475 EnterEqual();
01476 if (!inverse)
01477 memory_num += DISPLAY_AMOUNT;
01478 else {
01479 memory_num -= DISPLAY_AMOUNT;
01480 inverse = FALSE;
01481 }
01482 }
01483
01484 void QtCalculator::MC()
01485 {
01486
01487 memory_num = 0;
01488 refresh_display = 1;
01489 }
01490
01491 void QtCalculator::EnterEqual()
01492 {
01493 eestate = false;
01494 last_input = OPERATION;
01495 PushStack(&display_data);
01496 refresh_display = 1;
01497
01498
01499 UpdateStack(0);
01500
01501 UpdateDisplay();
01502 precedence_base = 0;
01503
01504 CALCAMNT* number ;
01505
01506 if(temp_stack.count() > TEMP_STACK_SIZE){
01507
01508 number = temp_stack.getFirst();
01509 temp_stack.removeFirst();
01510
01511 if(number)
01512 free(number);
01513 }
01514
01515 number = (CALCAMNT*) malloc(sizeof(CALCAMNT));
01516 *number = DISPLAY_AMOUNT;
01517
01518
01519
01520 temp_stack.append(number);
01521
01522
01523 }
01524
01525 void QtCalculator::Clear(){
01526
01527 eestate = false;
01528
01529 input_count = 0;
01530 decimal_point = 0;
01531
01532 if(last_input == OPERATION){
01533
01534 last_input = DIGIT;
01535 PopStack();
01536 }
01537 else{
01538
01539 last_input = DIGIT;
01540 }
01541
01542
01543 if( display_error){
01544 display_error = 0;
01545 refresh_display = 0;
01546 }
01547
01548 if (!refresh_display) {
01549 DISPLAY_AMOUNT = 0L;
01550 UpdateDisplay();
01551 }
01552
01553 }
01554
01555 void QtCalculator::ClearAll()
01556 {
01557
01558 eestate = false;
01559
01560 last_input = DIGIT;
01561 RefreshCalculator();
01562 refresh_display = 1;
01563
01564 }
01565
01566
01567
01568 void QtCalculator::UpdateDisplay()
01569 {
01570
01571
01572
01573
01574
01575 CALCAMNT boh_work_d;
01576 long boh_work = 0;
01577 int str_size = 0;
01578
01579 if(eestate && (current_base == NB_DECIMAL)){
01580
01581 calc_display->setText(display_str);
01582 return;
01583 }
01584
01585 if (current_base != NB_DECIMAL) {
01586 MODF(DISPLAY_AMOUNT, &boh_work_d);
01587 if (boh_work_d < LONG_MIN || boh_work_d > ULONG_MAX)
01588 display_error = 1;
01589
01590
01591
01592
01593
01594
01595
01596 else if (boh_work_d > LONG_MAX) {
01597 DISPLAY_AMOUNT =
01598 LONG_MIN+(boh_work_d-LONG_MAX-1);
01599 boh_work = (long)DISPLAY_AMOUNT;
01600 }
01601 else {
01602 DISPLAY_AMOUNT = boh_work_d;
01603 boh_work = (long) boh_work_d;
01604 }
01605 }
01606
01607 if (!display_error) {
01608
01609 if (current_base == NB_BINARY)
01610 str_size = cvb(display_str,
01611 boh_work,
01612 BOH_SIZE);
01613 else if (current_base == NB_OCTAL)
01614 str_size = sprintf(display_str,
01615 "%lo",
01616 boh_work);
01617 else if (current_base == NB_DECIMAL) {
01618
01619 if(!kcalcdefaults.fixed || last_input == DIGIT
01620 || (DISPLAY_AMOUNT > 1.0e+16)){
01621
01622
01623
01624
01625
01626 str_size = sprintf(display_str,
01627
01628 #ifdef HAVE_LONG_DOUBLE
01629 "%.*Lg",
01630
01631 kcalcdefaults.precision +1,
01632 #else
01633 "%.*g",
01634
01635 kcalcdefaults.precision +1,
01636 #endif
01637 DISPLAY_AMOUNT);
01638 }
01639 else{
01640
01641 str_size = sprintf(display_str,
01642
01643 #ifdef HAVE_LONG_DOUBLE
01644 "%.*Lf",
01645
01646 kcalcdefaults.fixedprecision ,
01647 #else
01648 "%.*f",
01649
01650 kcalcdefaults.fixedprecision ,
01651 #endif
01652 DISPLAY_AMOUNT);
01653
01654 }
01655
01656 if ( input_count > 0 && !strpbrk(display_str,"e") &&
01657 last_input == DIGIT ) {
01658
01659 #ifdef HAVE_LONG_DOUBLE
01660 str_size = sprintf(display_str,
01661 "%.*Lf",
01662 (kcalcdefaults.precision +1 > input_count)?
01663 input_count : kcalcdefaults.precision ,
01664 DISPLAY_AMOUNT);
01665 #else
01666 str_size = sprintf(display_str,
01667 "%.*f",
01668 (kcalcdefaults.precision +1 > input_count)?
01669 input_count : kcalcdefaults.precision ,
01670 DISPLAY_AMOUNT);
01671 #endif
01672 }
01673
01674 }
01675 else
01676 if (current_base == NB_HEX)
01677 str_size = sprintf(display_str,
01678 "%lX",
01679 boh_work);
01680 else
01681 display_error = 1;
01682 }
01683
01684 if (display_error || str_size < 0) {
01685 display_error = 1;
01686 strcpy(display_str,"Error");
01687 if(kcalcdefaults.beep)
01688 KNotifyClient::beep();
01689 }
01690 calc_display->setText(display_str);
01691
01692
01693 if (inverse){
01694 statusINVLabel->setText("INV");
01695 }
01696 else{
01697 statusINVLabel->setText("NORM");
01698 }
01699
01700 if (hyp_mode){
01701 statusHYPLabel->setText("HYP");
01702 }
01703 else{
01704 statusHYPLabel->setText("");
01705 }
01706
01707
01708 }
01709
01710 int cvb(char *out_str, long amount, int max_digits)
01711 {
01712
01713
01714
01715
01716
01717 char work_str[(sizeof(amount) * CHAR_BIT) + 1];
01718 int work_char = 0,
01719 lead_zero = 1,
01720 lead_one = 1,
01721 lead_one_count = 0,
01722 work_size = sizeof(amount) * CHAR_BIT;
01723 unsigned long bit_mask = (1 << ((sizeof(amount) * CHAR_BIT) - 1));
01724
01725 while (bit_mask) {
01726
01727 if (amount & bit_mask) {
01728 if (lead_one)
01729 lead_one_count++;
01730 lead_zero = 0;
01731 work_str[work_char++] = '1';
01732 } else {
01733 lead_one = 0;
01734 if (!lead_zero)
01735 work_str[work_char++] = '0';
01736 }
01737 bit_mask >>= 1;
01738 }
01739 if (!work_char)
01740 work_str[work_char++] = '0';
01741 work_str[work_char] = '\0';
01742
01743 if (work_char-lead_one_count < max_digits)
01744 return strlen(strcpy(out_str,
01745 &work_str[lead_one_count ?
01746 work_size - max_digits :
01747 0]));
01748 else
01749 return -1;
01750 }
01751
01752 int UpdateStack(int run_precedence)
01753 {
01754 item_contents new_item, *top_item , *top_function;
01755 CALCAMNT left_op =0.0 , right_op =0.0;
01756 int op_function= 0, return_value = 0;
01757
01758 new_item.s_item_type = ITEM_AMOUNT;
01759 while ((top_function = TopTypeStack(ITEM_FUNCTION)) &&
01760 top_function->s_item_data.item_func_data.item_precedence >=
01761 run_precedence) {
01762
01763 return_value = 1;
01764
01765 if ((top_item = PopStack())->s_item_type != ITEM_AMOUNT){
01766 KMessageBox::error( 0, "Stack processing error - right_op");
01767
01768 }
01769 right_op = top_item->s_item_data.item_amount;
01770
01771 if (!((top_item = PopStack()) &&
01772 top_item->s_item_type == ITEM_FUNCTION)) {
01773 KMessageBox::error( 0, "Stack processing error - function");
01774
01775 }
01776 op_function =
01777 top_item->s_item_data.item_func_data.item_function;
01778
01779 if (!((top_item = PopStack()) &&
01780 top_item->s_item_type == ITEM_AMOUNT)) {
01781 KMessageBox::error( 0, "Stack processing error - left_op");
01782 }
01783 left_op = top_item->s_item_data.item_amount;
01784
01785 new_item.s_item_data.item_amount =
01786 (Arith_ops[op_function])(left_op, right_op);
01787 PushStack(&new_item);
01788
01789 }
01790 if (return_value &&
01791 percent_mode &&
01792 !display_error &&
01793 Prcnt_ops[op_function] != NULL){
01794 new_item.s_item_data.item_amount =
01795 (Prcnt_ops[op_function])(left_op,
01796 right_op,
01797 new_item.s_item_data.item_amount);
01798 PushStack(&new_item);
01799 }
01800 if (return_value)
01801 DISPLAY_AMOUNT = new_item.s_item_data.item_amount;
01802
01803 return return_value;
01804 }
01805
01806 int isoddint(CALCAMNT input)
01807 {
01808 CALCAMNT dummy;
01809
01810
01811
01812 return (MODF(input, &dummy) == 0.0 &&
01813 MODF(input/2, &dummy) == 0.5);
01814 }
01815
01816 CALCAMNT ExecOr(CALCAMNT left_op, CALCAMNT right_op)
01817 {
01818
01819 CALCAMNT boh_work_d;
01820 long boh_work_l, boh_work_r;
01821
01822 MODF(left_op, &boh_work_d);
01823 if (FABS(boh_work_d) > LONG_MAX) {
01824 display_error = 1;
01825 return 0;
01826 }
01827 boh_work_l = (long int)boh_work_d;
01828 MODF(right_op, &boh_work_d);
01829 if (FABS(boh_work_d) > LONG_MAX) {
01830 display_error = 1;
01831 return 0;
01832 }
01833 boh_work_r = (long int) boh_work_d;
01834 return (boh_work_l | boh_work_r);
01835 }
01836
01837 CALCAMNT ExecXor(CALCAMNT left_op, CALCAMNT right_op)
01838 {
01839
01840 CALCAMNT boh_work_d;
01841 long boh_work_l, boh_work_r;
01842
01843 MODF(left_op, &boh_work_d);
01844 if (FABS(boh_work_d) > LONG_MAX) {
01845 display_error = 1;
01846 return 0;
01847 }
01848 boh_work_l = (long int) boh_work_d;
01849 MODF(right_op, &boh_work_d);
01850 if (FABS(boh_work_d) > LONG_MAX) {
01851 display_error = 1;
01852 return 0;
01853 }
01854 boh_work_r = (long int) boh_work_d;
01855 return (boh_work_l ^ boh_work_r);
01856 }
01857
01858 CALCAMNT ExecAnd(CALCAMNT left_op, CALCAMNT right_op)
01859 {
01860
01861 CALCAMNT boh_work_d;
01862 long boh_work_l, boh_work_r;
01863
01864 MODF(left_op, &boh_work_d);
01865 if (FABS(boh_work_d) > LONG_MAX) {
01866 display_error = 1;
01867 return 0;
01868 }
01869 boh_work_l = (long int ) boh_work_d;
01870 MODF(right_op, &boh_work_d);
01871 if (FABS(boh_work_d) > LONG_MAX) {
01872 display_error = 1;
01873 return 0;
01874 }
01875 boh_work_r = (long int ) boh_work_d;
01876 return (boh_work_l & boh_work_r);
01877 }
01878
01879 CALCAMNT ExecLsh(CALCAMNT left_op, CALCAMNT right_op)
01880 {
01881
01882 CALCAMNT boh_work_d;
01883 long boh_work_l, boh_work_r;
01884
01885 MODF(left_op, &boh_work_d);
01886 if (FABS(boh_work_d) > LONG_MAX) {
01887 display_error = 1;
01888 return 0;
01889 }
01890 boh_work_l = (long int) boh_work_d;
01891 MODF(right_op, &boh_work_d);
01892 if (FABS(boh_work_d) > LONG_MAX) {
01893 display_error = 1;
01894 return 0;
01895 }
01896 boh_work_r = (long int ) boh_work_d;
01897 return (boh_work_l << boh_work_r);
01898 }
01899
01900 CALCAMNT ExecRsh(CALCAMNT left_op, CALCAMNT right_op)
01901 {
01902
01903 CALCAMNT boh_work_d;
01904 long boh_work_l, boh_work_r;
01905
01906 MODF(left_op, &boh_work_d);
01907 if (FABS(boh_work_d) > LONG_MAX) {
01908 display_error = 1;
01909 return 0;
01910 }
01911 boh_work_l = (long int ) boh_work_d;
01912 MODF(right_op, &boh_work_d);
01913 if (FABS(boh_work_d) > LONG_MAX) {
01914 display_error = 1;
01915 return 0;
01916 }
01917 boh_work_r = ( long int ) boh_work_d;
01918 return (boh_work_l >> boh_work_r);
01919 }
01920
01921 CALCAMNT ExecAdd(CALCAMNT left_op, CALCAMNT right_op)
01922 {
01923
01924 return left_op + right_op;
01925 }
01926
01927 CALCAMNT ExecSubtract(CALCAMNT left_op, CALCAMNT right_op)
01928 {
01929
01930 return left_op - right_op;
01931 }
01932
01933 CALCAMNT ExecMultiply(CALCAMNT left_op, CALCAMNT right_op)
01934 {
01935
01936 return left_op * right_op;
01937 }
01938
01939 CALCAMNT ExecDivide(CALCAMNT left_op, CALCAMNT right_op)
01940 {
01941
01942 if (right_op == 0) {
01943 display_error = 1;
01944 return 0L;
01945 } else
01946 return left_op / right_op;
01947 }
01948
01949 CALCAMNT ExecMod(CALCAMNT left_op, CALCAMNT right_op)
01950 {
01951
01952 CALCAMNT temp =0.0;
01953
01954 if (right_op == 0) {
01955 display_error = 1;
01956 return 0L;
01957 } else {
01958
01959
01960 right_op = FABS(right_op);
01961
01962 temp = FMOD(left_op, right_op);
01963
01964
01965
01966
01967
01968 if( temp < 0 ) temp = right_op + temp;
01969 temp = FABS(temp);
01970
01971 return temp;
01972 }
01973 }
01974
01975 CALCAMNT ExecIntDiv(CALCAMNT left_op, CALCAMNT right_op)
01976 {
01977
01978 if (right_op == 0) {
01979 display_error = 1;
01980 return 0L;
01981 } else {
01982 MODF(left_op / right_op, &left_op);
01983 return left_op;
01984 }
01985 }
01986
01987 CALCAMNT ExecPower(CALCAMNT left_op, CALCAMNT right_op)
01988 {
01989
01990
01991 if (right_op == 0)
01992 return 1L;
01993 if (left_op < 0 && isoddint(1/right_op))
01994 left_op = -1L * POW((-1L * left_op), right_op);
01995 else
01996 left_op = POW(left_op, right_op);
01997 if (errno == EDOM || errno == ERANGE) {
01998 display_error = 1;
01999 return 0;
02000 } else
02001 return left_op;
02002 }
02003
02004 CALCAMNT ExecPwrRoot(CALCAMNT left_op, CALCAMNT right_op)
02005 {
02006
02007
02008 if (right_op == 0) {
02009 display_error = 1;
02010 return 0L;
02011 }
02012 if (left_op < 0 && isoddint(right_op))
02013 left_op = -1L * POW((-1L * left_op), (1L)/right_op);
02014 else
02015 left_op = POW(left_op, (1L)/right_op);
02016 if (errno == EDOM || errno == ERANGE) {
02017 display_error = 1;
02018 return 0;
02019 }
02020 else
02021 return left_op;
02022 }
02023
02024
02025 CALCAMNT ExecAddSubP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result)
02026 {
02027
02028 (void) left_op;
02029
02030 if (result == 0) {
02031 display_error = 1;
02032 return 0;
02033 } else
02034 return (result * 100L) / right_op;
02035 }
02036
02037 CALCAMNT ExecMultiplyP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result)
02038 {
02039
02040 (void) left_op;
02041 (void) right_op;
02042
02043 return (result / 100L);
02044 }
02045
02046 CALCAMNT ExecDivideP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result)
02047 {
02048
02049 (void) left_op;
02050 (void) right_op;
02051
02052 return (result * 100L);
02053 }
02054
02055 CALCAMNT ExecPowerP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result)
02056 {
02057
02058 (void) result;
02059 return ExecPower(left_op, (right_op / 100L));
02060 }
02061
02062 CALCAMNT ExecPwrRootP(CALCAMNT left_op, CALCAMNT right_op, CALCAMNT result)
02063 {
02064
02065 (void) result;
02066
02067 if (right_op == 0) {
02068 display_error = 1;
02069 return 0;
02070 } else
02071 return ExecPower(left_op, (100L / right_op));
02072 }
02073
02074
02075
02076 stack_ptr AllocStackItem (void) {
02077
02078 if (stack_next <= stack_last) {
02079
02080 process_stack[stack_next].prior_item = NULL;
02081 process_stack[stack_next].prior_type = NULL;
02082 return &process_stack[stack_next++];
02083 }
02084
02085 KMessageBox::error( 0, "Stack Error !");
02086 return &process_stack[stack_next];
02087 }
02088
02089 void UnAllocStackItem (stack_ptr return_item) {
02090
02091 if (return_item != &process_stack[--stack_next]) {
02092
02093 KMessageBox::error( 0, "Stack Error !");
02094 }
02095
02096 }
02097 void PushStack(item_contents *add_item)
02098 {
02099
02100
02101
02102
02103 stack_ptr new_item = top_of_stack;
02104
02105 if (!(new_item &&
02106 new_item->item_value.s_item_type == add_item->s_item_type)) {
02107
02108 new_item = AllocStackItem();
02109
02110
02111
02112
02113
02114 new_item->prior_item = top_of_stack;
02115 top_of_stack = new_item;
02116 new_item->prior_type = top_type_stack[add_item->s_item_type];
02117 top_type_stack[add_item->s_item_type] = new_item;
02118 }
02119
02120 new_item->item_value = *add_item;
02121
02122 }
02123
02124 item_contents *PopStack(void)
02125 {
02126
02127
02128
02129
02130 static item_contents return_item;
02131 item_contents *return_item_ptr = NULL;
02132 stack_ptr return_stack_ptr;
02133
02134 if ((return_stack_ptr = top_of_stack)) {
02135 return_item = top_of_stack->item_value;
02136
02137 top_type_stack[return_item.s_item_type]
02138 = top_of_stack->prior_type;
02139 top_of_stack = top_of_stack->prior_item;
02140
02141 UnAllocStackItem(return_stack_ptr);
02142 return_item_ptr = &return_item;
02143 }
02144
02145 return return_item_ptr;
02146 }
02147
02148 item_contents *TopOfStack(void)
02149 {
02150
02151
02152
02153
02154 item_contents *return_item_ptr = NULL;
02155
02156 if (top_of_stack) {
02157 return_item_ptr = &top_of_stack->item_value;
02158 }
02159
02160 return return_item_ptr;
02161 }
02162
02163 item_contents *TopTypeStack(item_type rqstd_type)
02164 {
02165
02166
02167
02168
02169 item_contents *return_item_ptr = NULL;
02170
02171 if (top_type_stack[rqstd_type]) {
02172 return_item_ptr = &top_type_stack[rqstd_type]->item_value;
02173 }
02174
02175 return return_item_ptr;
02176 }
02177
02178
02179
02180
02181
02182
02183
02184
02185 void InitStack (void) {
02186
02187 stack_next = 0;
02188 stack_last = STACK_SIZE - 1;
02189 top_of_stack = top_type_stack[0] = top_type_stack[1] = NULL;
02190 }
02191
02192