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