File indexing completed on 2024-04-28 09:45:26
0001 /* 0002 SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com> 0003 SPDX-FileCopyrightText: 2003-2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> 0004 SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org> 0005 SPDX-FileCopyrightText: 1995 Martin Bartlett 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "kcalc_core.h" 0011 #include "kcalc_settings.h" 0012 0013 #include <QDebug> 0014 0015 namespace 0016 { 0017 KNumber Deg2Rad(const KNumber &x) 0018 { 0019 return x * (KNumber::Pi() / KNumber(180)); 0020 } 0021 0022 KNumber Gra2Rad(const KNumber &x) 0023 { 0024 return x * (KNumber::Pi() / KNumber(200)); 0025 } 0026 0027 KNumber Rad2Deg(const KNumber &x) 0028 { 0029 return x * (KNumber(180) / KNumber::Pi()); 0030 } 0031 0032 KNumber Rad2Gra(const KNumber &x) 0033 { 0034 return x * (KNumber(200) / KNumber::Pi()); 0035 } 0036 0037 bool error_; 0038 0039 KNumber ExecOr(const KNumber &left_op, const KNumber &right_op) 0040 { 0041 return left_op | right_op; 0042 } 0043 0044 KNumber ExecXor(const KNumber &left_op, const KNumber &right_op) 0045 { 0046 return left_op ^ right_op; 0047 } 0048 0049 KNumber ExecAnd(const KNumber &left_op, const KNumber &right_op) 0050 { 0051 return left_op & right_op; 0052 } 0053 0054 KNumber ExecLsh(const KNumber &left_op, const KNumber &right_op) 0055 { 0056 return left_op << right_op; 0057 } 0058 0059 KNumber ExecRsh(const KNumber &left_op, const KNumber &right_op) 0060 { 0061 return left_op >> right_op; 0062 } 0063 0064 KNumber ExecAdd(const KNumber &left_op, const KNumber &right_op) 0065 { 0066 return left_op + right_op; 0067 } 0068 0069 KNumber ExecSubtract(const KNumber &left_op, const KNumber &right_op) 0070 { 0071 return left_op - right_op; 0072 } 0073 0074 KNumber ExecMultiply(const KNumber &left_op, const KNumber &right_op) 0075 { 0076 return left_op * right_op; 0077 } 0078 0079 KNumber ExecDivide(const KNumber &left_op, const KNumber &right_op) 0080 { 0081 return left_op / right_op; 0082 } 0083 0084 KNumber ExecMod(const KNumber &left_op, const KNumber &right_op) 0085 { 0086 return left_op % right_op; 0087 } 0088 0089 KNumber ExecIntDiv(const KNumber &left_op, const KNumber &right_op) 0090 { 0091 return (left_op / right_op).integerPart(); 0092 } 0093 0094 KNumber ExecBinom(const KNumber &left_op, const KNumber &right_op) 0095 { 0096 return left_op.bin(right_op); 0097 } 0098 0099 KNumber ExecPower(const KNumber &left_op, const KNumber &right_op) 0100 { 0101 return left_op.pow(right_op); 0102 } 0103 0104 KNumber ExecPwrRoot(const KNumber &left_op, const KNumber &right_op) 0105 { 0106 return left_op.pow(KNumber::One / right_op); 0107 } 0108 0109 KNumber ExecAddP(const KNumber &left_op, const KNumber &right_op) 0110 { 0111 return left_op * (KNumber::One + right_op / KNumber(100)); 0112 } 0113 0114 KNumber ExecSubP(const KNumber &left_op, const KNumber &right_op) 0115 { 0116 return left_op * (KNumber::One - right_op / KNumber(100)); 0117 } 0118 0119 KNumber ExecMultiplyP(const KNumber &left_op, const KNumber &right_op) 0120 { 0121 return left_op * right_op / KNumber(100); 0122 } 0123 0124 KNumber ExecDivideP(const KNumber &left_op, const KNumber &right_op) 0125 { 0126 return left_op * KNumber(100) / right_op; 0127 } 0128 0129 // move a number into the interval [0,360) by adding multiples of 360 0130 KNumber moveIntoDegInterval(const KNumber &num) 0131 { 0132 KNumber tmp_num = num - (num / KNumber(360)).integerPart() * KNumber(360); 0133 if (tmp_num < KNumber::Zero) 0134 return tmp_num + KNumber(360); 0135 return tmp_num; 0136 } 0137 0138 // move a number into the interval [0,400) by adding multiples of 400 0139 KNumber moveIntoGradInterval(const KNumber &num) 0140 { 0141 KNumber tmp_num = num - (num / KNumber(400)).integerPart() * KNumber(400); 0142 if (tmp_num < KNumber::Zero) 0143 return tmp_num + KNumber(400); 0144 return tmp_num; 0145 } 0146 0147 typedef KNumber (*Arith)(const KNumber &, const KNumber &); 0148 typedef KNumber (*Prcnt)(const KNumber &, const KNumber &); 0149 0150 struct operator_data { 0151 int precedence; // priority of operators in " enum Operation" 0152 Arith arith_ptr; 0153 Prcnt prcnt_ptr; 0154 }; 0155 0156 // build precedence list 0157 const struct operator_data Operator[] = { 0158 {0, nullptr, nullptr}, // FUNC_EQUAL 0159 {0, nullptr, nullptr}, // FUNC_PERCENT 0160 {0, nullptr, nullptr}, // FUNC_BRACKET 0161 {1, ExecOr, nullptr}, // FUNC_OR 0162 {2, ExecXor, nullptr}, // FUNC_XOR 0163 {3, ExecAnd, nullptr}, // FUNC_AND 0164 {4, ExecLsh, nullptr}, // FUNC_LSH 0165 {4, ExecRsh, nullptr}, // FUNC_RSH 0166 {5, ExecAdd, ExecAddP}, // FUNC_ADD 0167 {5, ExecSubtract, ExecSubP}, // FUNC_SUBTRACT 0168 {6, ExecMultiply, ExecMultiplyP}, // FUNC_MULTIPLY 0169 {6, ExecDivide, ExecDivideP}, // FUNC_DIVIDE 0170 {6, ExecMod, nullptr}, // FUNC_MOD 0171 {6, ExecIntDiv, nullptr}, // FUNC_INTDIV 0172 {7, ExecBinom, nullptr}, // FUNC_BINOM 0173 {7, ExecPower, nullptr}, // FUNC_POWER 0174 {7, ExecPwrRoot, nullptr} // FUNC_PWR_ROOT 0175 }; 0176 0177 } 0178 0179 CalcEngine::CalcEngine() 0180 : last_number_(KNumber::Zero) 0181 , only_update_operation_(false) 0182 , percent_mode_(false) 0183 , repeat_mode_(false) 0184 { 0185 error_ = false; 0186 last_operation_ = FUNC_EQUAL; 0187 } 0188 0189 KNumber CalcEngine::lastOutput(bool &error) const 0190 { 0191 error = error_; 0192 return last_number_; 0193 } 0194 0195 void CalcEngine::ArcCosDeg(const KNumber &input) 0196 { 0197 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0198 last_number_ = KNumber::NaN; 0199 return; 0200 } 0201 0202 if (input.type() == KNumber::TYPE_INTEGER) { 0203 if (input == KNumber::One) { 0204 last_number_ = KNumber::Zero; 0205 return; 0206 } 0207 if (input == -KNumber::One) { 0208 last_number_ = KNumber(180); 0209 return; 0210 } 0211 if (input == KNumber::Zero) { 0212 last_number_ = KNumber(90); 0213 return; 0214 } 0215 } 0216 last_number_ = Rad2Deg(input.acos()); 0217 } 0218 0219 void CalcEngine::ArcCosRad(const KNumber &input) 0220 { 0221 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0222 last_number_ = KNumber::NaN; 0223 return; 0224 } 0225 last_number_ = input.acos(); 0226 } 0227 0228 void CalcEngine::ArcCosGrad(const KNumber &input) 0229 { 0230 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0231 last_number_ = KNumber::NaN; 0232 return; 0233 } 0234 if (input.type() == KNumber::TYPE_INTEGER) { 0235 if (input == KNumber::One) { 0236 last_number_ = KNumber::Zero; 0237 return; 0238 } 0239 if (input == -KNumber::One) { 0240 last_number_ = KNumber(200); 0241 return; 0242 } 0243 if (input == KNumber::Zero) { 0244 last_number_ = KNumber(100); 0245 return; 0246 } 0247 } 0248 last_number_ = Rad2Gra(input.acos()); 0249 } 0250 0251 void CalcEngine::ArcSinDeg(const KNumber &input) 0252 { 0253 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0254 last_number_ = KNumber::NaN; 0255 return; 0256 } 0257 if (input.type() == KNumber::TYPE_INTEGER) { 0258 if (input == KNumber::One) { 0259 last_number_ = KNumber(90); 0260 return; 0261 } 0262 if (input == -KNumber::One) { 0263 last_number_ = KNumber(-90); 0264 return; 0265 } 0266 if (input == KNumber::Zero) { 0267 last_number_ = KNumber::Zero; 0268 return; 0269 } 0270 } 0271 last_number_ = Rad2Deg(input.asin()); 0272 } 0273 0274 void CalcEngine::ArcSinRad(const KNumber &input) 0275 { 0276 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0277 last_number_ = KNumber::NaN; 0278 return; 0279 } 0280 last_number_ = input.asin(); 0281 } 0282 0283 void CalcEngine::ArcSinGrad(const KNumber &input) 0284 { 0285 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0286 last_number_ = KNumber::NaN; 0287 return; 0288 } 0289 if (input.type() == KNumber::TYPE_INTEGER) { 0290 if (input == KNumber::One) { 0291 last_number_ = KNumber(100); 0292 return; 0293 } 0294 if (input == -KNumber::One) { 0295 last_number_ = KNumber(-100); 0296 return; 0297 } 0298 if (input == KNumber::Zero) { 0299 last_number_ = KNumber::Zero; 0300 return; 0301 } 0302 } 0303 last_number_ = Rad2Gra(input.asin()); 0304 } 0305 0306 void CalcEngine::ArcTangensDeg(const KNumber &input) 0307 { 0308 if (input.type() == KNumber::TYPE_ERROR) { 0309 if (input == KNumber::NaN) 0310 last_number_ = KNumber::NaN; 0311 if (input == KNumber::PosInfinity) 0312 last_number_ = KNumber(90); 0313 if (input == KNumber::NegInfinity) 0314 last_number_ = KNumber(-90); 0315 return; 0316 } 0317 0318 last_number_ = Rad2Deg(input.atan()); 0319 } 0320 0321 void CalcEngine::ArcTangensRad(const KNumber &input) 0322 { 0323 if (input.type() == KNumber::TYPE_ERROR) { 0324 if (input == KNumber::NaN) 0325 last_number_ = KNumber::NaN; 0326 if (input == KNumber::PosInfinity) 0327 last_number_ = KNumber::Pi() / KNumber(2); 0328 if (input == KNumber::NegInfinity) 0329 last_number_ = -KNumber::Pi() / KNumber(2); 0330 return; 0331 } 0332 0333 last_number_ = input.atan(); 0334 } 0335 0336 void CalcEngine::ArcTangensGrad(const KNumber &input) 0337 { 0338 if (input.type() == KNumber::TYPE_ERROR) { 0339 if (input == KNumber::NaN) 0340 last_number_ = KNumber::NaN; 0341 if (input == KNumber::PosInfinity) 0342 last_number_ = KNumber(100); 0343 if (input == KNumber::NegInfinity) 0344 last_number_ = KNumber(-100); 0345 return; 0346 } 0347 0348 last_number_ = Rad2Gra(input.atan()); 0349 } 0350 0351 void CalcEngine::AreaCosHyp(const KNumber &input) 0352 { 0353 if (input.type() == KNumber::TYPE_ERROR) { 0354 if (input == KNumber::NaN) 0355 last_number_ = KNumber::NaN; 0356 if (input == KNumber::PosInfinity) 0357 last_number_ = KNumber::PosInfinity; 0358 if (input == KNumber::NegInfinity) 0359 last_number_ = KNumber::NaN; 0360 return; 0361 } 0362 0363 if (input < KNumber::One) { 0364 last_number_ = KNumber::NaN; 0365 return; 0366 } 0367 if (input == KNumber::One) { 0368 last_number_ = KNumber::Zero; 0369 return; 0370 } 0371 last_number_ = input.acosh(); 0372 } 0373 0374 void CalcEngine::AreaSinHyp(const KNumber &input) 0375 { 0376 if (input.type() == KNumber::TYPE_ERROR) { 0377 if (input == KNumber::NaN) 0378 last_number_ = KNumber::NaN; 0379 if (input == KNumber::PosInfinity) 0380 last_number_ = KNumber::PosInfinity; 0381 if (input == KNumber::NegInfinity) 0382 last_number_ = KNumber::NegInfinity; 0383 return; 0384 } 0385 0386 if (input == KNumber::Zero) { 0387 last_number_ = KNumber::Zero; 0388 return; 0389 } 0390 last_number_ = input.asinh(); 0391 } 0392 0393 void CalcEngine::AreaTangensHyp(const KNumber &input) 0394 { 0395 if (input.type() == KNumber::TYPE_ERROR) { 0396 last_number_ = KNumber::NaN; 0397 return; 0398 } 0399 0400 if (input < -KNumber::One || input > KNumber::One) { 0401 last_number_ = KNumber::NaN; 0402 return; 0403 } 0404 if (input == KNumber::One) { 0405 last_number_ = KNumber::PosInfinity; 0406 return; 0407 } 0408 if (input == -KNumber::One) { 0409 last_number_ = KNumber::NegInfinity; 0410 return; 0411 } 0412 last_number_ = input.atanh(); 0413 } 0414 0415 void CalcEngine::Complement(const KNumber &input) 0416 { 0417 if (input.type() != KNumber::TYPE_INTEGER) { 0418 last_number_ = KNumber::NaN; 0419 return; 0420 } 0421 0422 last_number_ = ~input; 0423 } 0424 0425 void CalcEngine::CosDeg(const KNumber &input) 0426 { 0427 if (input.type() == KNumber::TYPE_ERROR) { 0428 last_number_ = KNumber::NaN; 0429 return; 0430 } 0431 0432 KNumber trunc_input = moveIntoDegInterval(input); 0433 0434 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0435 KNumber mult = trunc_input / KNumber(90); 0436 if (mult.type() == KNumber::TYPE_INTEGER) { 0437 if (mult == KNumber::Zero) 0438 last_number_ = KNumber::One; 0439 else if (mult == KNumber::One) 0440 last_number_ = KNumber::Zero; 0441 else if (mult == KNumber(2)) 0442 last_number_ = KNumber::NegOne; 0443 else if (mult == KNumber(3)) 0444 last_number_ = KNumber::Zero; 0445 else 0446 qDebug() << "Something wrong in CalcEngine::CosDeg"; 0447 return; 0448 } 0449 } 0450 0451 trunc_input = Deg2Rad(trunc_input); 0452 last_number_ = trunc_input.cos(); 0453 } 0454 0455 void CalcEngine::CosRad(const KNumber &input) 0456 { 0457 if (input.type() == KNumber::TYPE_ERROR) { 0458 last_number_ = KNumber::NaN; 0459 return; 0460 } 0461 0462 last_number_ = input.cos(); 0463 } 0464 0465 void CalcEngine::CosGrad(const KNumber &input) 0466 { 0467 if (input.type() == KNumber::TYPE_ERROR) { 0468 last_number_ = KNumber::NaN; 0469 return; 0470 } 0471 KNumber trunc_input = moveIntoGradInterval(input); 0472 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0473 KNumber mult = trunc_input / KNumber(100); 0474 if (mult.type() == KNumber::TYPE_INTEGER) { 0475 if (mult == KNumber::Zero) 0476 last_number_ = KNumber::One; 0477 else if (mult == KNumber::One) 0478 last_number_ = KNumber::Zero; 0479 else if (mult == KNumber(2)) 0480 last_number_ = KNumber::NegOne; 0481 else if (mult == KNumber(3)) 0482 last_number_ = KNumber::Zero; 0483 else 0484 qDebug() << "Something wrong in CalcEngine::CosGrad"; 0485 return; 0486 } 0487 } 0488 trunc_input = Gra2Rad(trunc_input); 0489 0490 last_number_ = trunc_input.cos(); 0491 } 0492 0493 void CalcEngine::CosHyp(const KNumber &input) 0494 { 0495 if (input.type() == KNumber::TYPE_ERROR) { 0496 if (input == KNumber::NaN) 0497 last_number_ = KNumber::NaN; 0498 if (input == KNumber::PosInfinity) 0499 last_number_ = KNumber::PosInfinity; 0500 // YES, this should be *positive* infinity. We mimic the behavior of 0501 // libc which says the following for cosh 0502 // 0503 // "If x is positive infinity or negative infinity, positive infinity is returned." 0504 if (input == KNumber::NegInfinity) 0505 last_number_ = KNumber::PosInfinity; 0506 return; 0507 } 0508 0509 last_number_ = input.cosh(); 0510 } 0511 0512 void CalcEngine::Cube(const KNumber &input) 0513 { 0514 last_number_ = input * input * input; 0515 } 0516 0517 void CalcEngine::CubeRoot(const KNumber &input) 0518 { 0519 last_number_ = input.cbrt(); 0520 } 0521 0522 void CalcEngine::Exp(const KNumber &input) 0523 { 0524 if (input.type() == KNumber::TYPE_ERROR) { 0525 if (input == KNumber::NaN) 0526 last_number_ = KNumber::NaN; 0527 if (input == KNumber::PosInfinity) 0528 last_number_ = KNumber::PosInfinity; 0529 if (input == KNumber::NegInfinity) 0530 last_number_ = KNumber::Zero; 0531 return; 0532 } 0533 last_number_ = KNumber::Euler().pow(input); 0534 } 0535 0536 void CalcEngine::Exp10(const KNumber &input) 0537 { 0538 if (input.type() == KNumber::TYPE_ERROR) { 0539 if (input == KNumber::NaN) 0540 last_number_ = KNumber::NaN; 0541 if (input == KNumber::PosInfinity) 0542 last_number_ = KNumber::PosInfinity; 0543 if (input == KNumber::NegInfinity) 0544 last_number_ = KNumber::Zero; 0545 return; 0546 } 0547 last_number_ = KNumber(10).pow(input); 0548 } 0549 0550 void CalcEngine::Factorial(const KNumber &input) 0551 { 0552 if (input == KNumber::PosInfinity) 0553 return; 0554 if (input < KNumber::Zero || input.type() == KNumber::TYPE_ERROR) { 0555 error_ = true; 0556 last_number_ = KNumber::NaN; 0557 return; 0558 } 0559 0560 last_number_ = input.integerPart().factorial(); 0561 } 0562 0563 void CalcEngine::Gamma(const KNumber &input) 0564 { 0565 if (input == KNumber::PosInfinity) 0566 return; 0567 if (input < KNumber::Zero || input.type() == KNumber::TYPE_ERROR) { 0568 error_ = true; 0569 last_number_ = KNumber::NaN; 0570 return; 0571 } 0572 0573 last_number_ = input.tgamma(); 0574 } 0575 0576 void CalcEngine::InvertSign(const KNumber &input) 0577 { 0578 last_number_ = -input; 0579 } 0580 0581 void CalcEngine::Ln(const KNumber &input) 0582 { 0583 if (input < KNumber::Zero) 0584 last_number_ = KNumber::NaN; 0585 else if (input == KNumber::Zero) 0586 last_number_ = KNumber::NegInfinity; 0587 else if (input == KNumber::One) 0588 last_number_ = KNumber::Zero; 0589 else { 0590 last_number_ = input.ln(); 0591 } 0592 } 0593 0594 void CalcEngine::Log10(const KNumber &input) 0595 { 0596 if (input < KNumber::Zero) 0597 last_number_ = KNumber::NaN; 0598 else if (input == KNumber::Zero) 0599 last_number_ = KNumber::NegInfinity; 0600 else if (input == KNumber::One) 0601 last_number_ = KNumber::Zero; 0602 else { 0603 last_number_ = input.log10(); 0604 } 0605 } 0606 0607 void CalcEngine::ParenClose(KNumber input) 0608 { 0609 // evaluate stack until corresponding opening bracket 0610 while (!stack_.isEmpty()) { 0611 Node tmp_node = stack_.pop(); 0612 if (tmp_node.operation == FUNC_BRACKET) 0613 break; 0614 input = evalOperation(tmp_node.number, tmp_node.operation, input); 0615 } 0616 last_number_ = input; 0617 } 0618 0619 void CalcEngine::ParenOpen(const KNumber &input) 0620 { 0621 enterOperation(input, FUNC_BRACKET); 0622 } 0623 0624 void CalcEngine::Reciprocal(const KNumber &input) 0625 { 0626 last_number_ = KNumber::One / input; 0627 } 0628 0629 void CalcEngine::SinDeg(const KNumber &input) 0630 { 0631 if (input.type() == KNumber::TYPE_ERROR) { 0632 last_number_ = KNumber::NaN; 0633 return; 0634 } 0635 0636 KNumber trunc_input = moveIntoDegInterval(input); 0637 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0638 KNumber mult = trunc_input / KNumber(90); 0639 if (mult.type() == KNumber::TYPE_INTEGER) { 0640 if (mult == KNumber::Zero) 0641 last_number_ = KNumber::Zero; 0642 else if (mult == KNumber::One) 0643 last_number_ = KNumber::One; 0644 else if (mult == KNumber(2)) 0645 last_number_ = KNumber::Zero; 0646 else if (mult == KNumber(3)) 0647 last_number_ = KNumber::NegOne; 0648 else 0649 qDebug() << "Something wrong in CalcEngine::SinDeg"; 0650 return; 0651 } 0652 } 0653 trunc_input = Deg2Rad(trunc_input); 0654 0655 last_number_ = trunc_input.sin(); 0656 } 0657 0658 void CalcEngine::SinRad(const KNumber &input) 0659 { 0660 if (input.type() == KNumber::TYPE_ERROR) { 0661 last_number_ = KNumber::NaN; 0662 return; 0663 } 0664 0665 last_number_ = input.sin(); 0666 } 0667 0668 void CalcEngine::SinGrad(const KNumber &input) 0669 { 0670 if (input.type() == KNumber::TYPE_ERROR) { 0671 last_number_ = KNumber::NaN; 0672 return; 0673 } 0674 0675 KNumber trunc_input = moveIntoGradInterval(input); 0676 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0677 KNumber mult = trunc_input / KNumber(100); 0678 if (mult.type() == KNumber::TYPE_INTEGER) { 0679 if (mult == KNumber::Zero) 0680 last_number_ = KNumber::Zero; 0681 else if (mult == KNumber::One) 0682 last_number_ = KNumber::One; 0683 else if (mult == KNumber(2)) 0684 last_number_ = KNumber::Zero; 0685 else if (mult == KNumber(3)) 0686 last_number_ = KNumber::NegOne; 0687 else 0688 qDebug() << "Something wrong in CalcEngine::SinGrad"; 0689 return; 0690 } 0691 } 0692 0693 trunc_input = Gra2Rad(trunc_input); 0694 0695 last_number_ = trunc_input.sin(); 0696 } 0697 0698 void CalcEngine::SinHyp(const KNumber &input) 0699 { 0700 if (input.type() == KNumber::TYPE_ERROR) { 0701 if (input == KNumber::NaN) 0702 last_number_ = KNumber::NaN; 0703 if (input == KNumber::PosInfinity) 0704 last_number_ = KNumber::PosInfinity; 0705 if (input == KNumber::NegInfinity) 0706 last_number_ = KNumber::NegInfinity; 0707 return; 0708 } 0709 0710 last_number_ = input.sinh(); 0711 } 0712 0713 void CalcEngine::Square(const KNumber &input) 0714 { 0715 last_number_ = input * input; 0716 } 0717 0718 void CalcEngine::SquareRoot(const KNumber &input) 0719 { 0720 last_number_ = input.sqrt(); 0721 } 0722 0723 void CalcEngine::StatClearAll(const KNumber &input) 0724 { 0725 Q_UNUSED(input); 0726 stats.clearAll(); 0727 } 0728 0729 void CalcEngine::StatCount(const KNumber &input) 0730 { 0731 Q_UNUSED(input); 0732 last_number_ = KNumber(stats.count()); 0733 } 0734 0735 void CalcEngine::StatDataNew(const KNumber &input) 0736 { 0737 stats.enterData(input); 0738 last_number_ = KNumber(stats.count()); 0739 } 0740 0741 void CalcEngine::StatDataDel(const KNumber &input) 0742 { 0743 Q_UNUSED(input); 0744 stats.clearLast(); 0745 last_number_ = KNumber(stats.count()); 0746 } 0747 0748 void CalcEngine::StatMean(const KNumber &input) 0749 { 0750 Q_UNUSED(input); 0751 last_number_ = stats.mean(); 0752 0753 error_ = stats.error(); 0754 } 0755 0756 void CalcEngine::StatMedian(const KNumber &input) 0757 { 0758 Q_UNUSED(input); 0759 last_number_ = stats.median(); 0760 0761 error_ = stats.error(); 0762 } 0763 0764 void CalcEngine::StatStdDeviation(const KNumber &input) 0765 { 0766 Q_UNUSED(input); 0767 last_number_ = stats.std(); 0768 0769 error_ = stats.error(); 0770 } 0771 0772 void CalcEngine::StatStdSample(const KNumber &input) 0773 { 0774 Q_UNUSED(input); 0775 last_number_ = stats.sample_std(); 0776 0777 error_ = stats.error(); 0778 } 0779 0780 void CalcEngine::StatSum(const KNumber &input) 0781 { 0782 Q_UNUSED(input); 0783 last_number_ = stats.sum(); 0784 } 0785 0786 void CalcEngine::StatSumSquares(const KNumber &input) 0787 { 0788 Q_UNUSED(input); 0789 last_number_ = stats.sum_of_squares(); 0790 0791 error_ = stats.error(); 0792 } 0793 0794 void CalcEngine::TangensDeg(const KNumber &input) 0795 { 0796 if (input.type() == KNumber::TYPE_ERROR) { 0797 last_number_ = KNumber::NaN; 0798 return; 0799 } 0800 0801 SinDeg(input); 0802 KNumber arg1 = last_number_; 0803 CosDeg(input); 0804 KNumber arg2 = last_number_; 0805 0806 last_number_ = arg1 / arg2; 0807 } 0808 0809 void CalcEngine::TangensRad(const KNumber &input) 0810 { 0811 if (input.type() == KNumber::TYPE_ERROR) { 0812 last_number_ = KNumber::NaN; 0813 return; 0814 } 0815 0816 SinRad(input); 0817 KNumber arg1 = last_number_; 0818 CosRad(input); 0819 KNumber arg2 = last_number_; 0820 0821 last_number_ = arg1 / arg2; 0822 } 0823 0824 void CalcEngine::TangensGrad(const KNumber &input) 0825 { 0826 if (input.type() == KNumber::TYPE_ERROR) { 0827 last_number_ = KNumber::NaN; 0828 return; 0829 } 0830 0831 SinGrad(input); 0832 KNumber arg1 = last_number_; 0833 CosGrad(input); 0834 KNumber arg2 = last_number_; 0835 0836 last_number_ = arg1 / arg2; 0837 } 0838 0839 void CalcEngine::TangensHyp(const KNumber &input) 0840 { 0841 if (input.type() == KNumber::TYPE_ERROR) { 0842 if (input == KNumber::NaN) 0843 last_number_ = KNumber::NaN; 0844 if (input == KNumber::PosInfinity) 0845 last_number_ = KNumber::One; 0846 if (input == KNumber::NegInfinity) 0847 last_number_ = KNumber::NegOne; 0848 return; 0849 } 0850 0851 last_number_ = input.tanh(); 0852 } 0853 0854 KNumber CalcEngine::evalOperation(const KNumber &arg1, Operation operation, const KNumber &arg2) 0855 { 0856 if (!percent_mode_ || Operator[operation].prcnt_ptr == nullptr) { 0857 return (Operator[operation].arith_ptr)(arg1, arg2); 0858 } else { 0859 percent_mode_ = false; 0860 return (Operator[operation].prcnt_ptr)(arg1, arg2); 0861 } 0862 } 0863 0864 void CalcEngine::enterOperation(const KNumber &number, Operation func, Repeat allow_repeat) 0865 { 0866 Node tmp_node; 0867 0868 if (func == FUNC_BRACKET) { 0869 tmp_node.number = KNumber::Zero; 0870 tmp_node.operation = FUNC_BRACKET; 0871 0872 stack_.push(tmp_node); 0873 0874 return; 0875 } 0876 0877 if (func == FUNC_PERCENT) { 0878 percent_mode_ = true; 0879 } 0880 0881 tmp_node.number = number; 0882 tmp_node.operation = func; 0883 0884 if (KCalcSettings::repeatLastOperation()) { 0885 if (func != FUNC_EQUAL && func != FUNC_PERCENT) { 0886 last_operation_ = tmp_node.operation; 0887 repeat_mode_ = false; 0888 } 0889 0890 if (func == FUNC_EQUAL || func == FUNC_PERCENT) { 0891 if (!repeat_mode_) { 0892 repeat_mode_ = last_operation_ != FUNC_EQUAL; 0893 last_repeat_number_ = number; 0894 } else if (allow_repeat == REPEAT_ALLOW) { 0895 Node repeat_node; 0896 repeat_node.operation = last_operation_; 0897 repeat_node.number = number; 0898 tmp_node.number = last_repeat_number_; 0899 stack_.push(repeat_node); 0900 } 0901 } 0902 } 0903 0904 if (getOnlyUpdateOperation() && !stack_.isEmpty() && !(func == FUNC_EQUAL || func == FUNC_PERCENT)) 0905 stack_.top().operation = func; 0906 else 0907 stack_.push(tmp_node); 0908 0909 // The check for '=' or '%' is unnecessary; it is just a safety measure 0910 if (!((func == FUNC_EQUAL) || (func == FUNC_PERCENT))) 0911 setOnlyUpdateOperation(true); 0912 0913 evalStack(); 0914 } 0915 0916 bool CalcEngine::evalStack() 0917 { 0918 // this should never happen 0919 Q_ASSERT(!stack_.isEmpty()); 0920 0921 Node tmp_node = stack_.pop(); 0922 0923 while (!stack_.isEmpty()) { 0924 Node tmp_node2 = stack_.pop(); 0925 if (Operator[tmp_node.operation].precedence <= Operator[tmp_node2.operation].precedence) { 0926 if (tmp_node2.operation == FUNC_BRACKET) 0927 continue; 0928 const KNumber tmp_result = evalOperation(tmp_node2.number, tmp_node2.operation, tmp_node.number); 0929 tmp_node.number = tmp_result; 0930 } else { 0931 stack_.push(tmp_node2); 0932 break; 0933 } 0934 } 0935 0936 if (tmp_node.operation != FUNC_EQUAL && tmp_node.operation != FUNC_PERCENT) 0937 stack_.push(tmp_node); 0938 0939 last_number_ = tmp_node.number; 0940 return true; 0941 } 0942 0943 void CalcEngine::Reset() 0944 { 0945 percent_mode_ = false; 0946 repeat_mode_ = false; 0947 last_operation_ = FUNC_EQUAL; 0948 error_ = false; 0949 last_number_ = KNumber::Zero; 0950 only_update_operation_ = false; 0951 0952 stack_.clear(); 0953 } 0954 0955 void CalcEngine::setOnlyUpdateOperation(bool update) 0956 { 0957 only_update_operation_ = update; 0958 } 0959 0960 bool CalcEngine::getOnlyUpdateOperation() const 0961 { 0962 return only_update_operation_; 0963 }