File indexing completed on 2024-04-28 05:49:44
0001 /* 0002 SPDX-FileCopyrightText: 2023 Gabriel Barrantes <gabriel.barrantes.dev@outlook.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "kcalc_core_p.h" 0007 #include "knumber.h" 0008 #include "stats.h" 0009 0010 KNumber CalcEngine_p::Deg2Rad(const KNumber &x) 0011 { 0012 return x * (KNumber::Pi() / KNumber(180)); 0013 } 0014 0015 KNumber CalcEngine_p::Gra2Rad(const KNumber &x) 0016 { 0017 return x * (KNumber::Pi() / KNumber(200)); 0018 } 0019 0020 KNumber CalcEngine_p::Rad2Deg(const KNumber &x) 0021 { 0022 return x * (KNumber(180) / KNumber::Pi()); 0023 } 0024 0025 KNumber CalcEngine_p::Rad2Gra(const KNumber &x) 0026 { 0027 return x * (KNumber(200) / KNumber::Pi()); 0028 } 0029 0030 KNumber CalcEngine_p::ExecOr(const KNumber &left_op, const KNumber &right_op) 0031 { 0032 return left_op | right_op; 0033 } 0034 0035 KNumber CalcEngine_p::ExecXor(const KNumber &left_op, const KNumber &right_op) 0036 { 0037 return left_op ^ right_op; 0038 } 0039 0040 KNumber CalcEngine_p::ExecAnd(const KNumber &left_op, const KNumber &right_op) 0041 { 0042 return left_op & right_op; 0043 } 0044 0045 KNumber CalcEngine_p::ExecLsh(const KNumber &left_op, const KNumber &right_op) 0046 { 0047 return left_op << right_op; 0048 } 0049 0050 KNumber CalcEngine_p::ExecRsh(const KNumber &left_op, const KNumber &right_op) 0051 { 0052 return left_op >> right_op; 0053 } 0054 0055 KNumber CalcEngine_p::ExecAdd(const KNumber &left_op, const KNumber &right_op) 0056 { 0057 return left_op + right_op; 0058 } 0059 0060 KNumber CalcEngine_p::ExecSubtract(const KNumber &left_op, const KNumber &right_op) 0061 { 0062 return left_op - right_op; 0063 } 0064 0065 KNumber CalcEngine_p::ExecMultiply(const KNumber &left_op, const KNumber &right_op) 0066 { 0067 return left_op * right_op; 0068 } 0069 0070 KNumber CalcEngine_p::ExecDivide(const KNumber &left_op, const KNumber &right_op) 0071 { 0072 return left_op / right_op; 0073 } 0074 0075 KNumber CalcEngine_p::ExecMod(const KNumber &left_op, const KNumber &right_op) 0076 { 0077 return left_op % right_op; 0078 } 0079 0080 KNumber CalcEngine_p::ExecIntDiv(const KNumber &left_op, const KNumber &right_op) 0081 { 0082 return (left_op / right_op).integerPart(); 0083 } 0084 0085 KNumber CalcEngine_p::ExecBinom(const KNumber &left_op, const KNumber &right_op) 0086 { 0087 return left_op.bin(right_op); 0088 } 0089 0090 KNumber CalcEngine_p::ExecPower(const KNumber &left_op, const KNumber &right_op) 0091 { 0092 return left_op.pow(right_op); 0093 } 0094 0095 KNumber CalcEngine_p::ExecPwrRoot(const KNumber &left_op, const KNumber &right_op) 0096 { 0097 return left_op.pow(KNumber::One / right_op); 0098 } 0099 0100 KNumber CalcEngine_p::ExecAddP(const KNumber &left_op, const KNumber &right_op) 0101 { 0102 return left_op * (KNumber::One + right_op / KNumber(100)); 0103 } 0104 0105 KNumber CalcEngine_p::ExecSubP(const KNumber &left_op, const KNumber &right_op) 0106 { 0107 return left_op * (KNumber::One - right_op / KNumber(100)); 0108 } 0109 0110 KNumber CalcEngine_p::ExecMultiplyP(const KNumber &left_op, const KNumber &right_op) 0111 { 0112 return left_op * right_op / KNumber(100); 0113 } 0114 0115 KNumber CalcEngine_p::ExecDivideP(const KNumber &left_op, const KNumber &right_op) 0116 { 0117 return left_op * KNumber(100) / right_op; 0118 } 0119 0120 // move a number into the interval [0,360) by adding multiples of 360 0121 KNumber CalcEngine_p::moveIntoDegInterval(const KNumber &num) 0122 { 0123 KNumber tmp_num = num - (num / KNumber(360)).integerPart() * KNumber(360); 0124 if (tmp_num < KNumber::Zero) 0125 return tmp_num + KNumber(360); 0126 return tmp_num; 0127 } 0128 0129 // move a number into the interval [0,400) by adding multiples of 400 0130 KNumber CalcEngine_p::moveIntoGradInterval(const KNumber &num) 0131 { 0132 KNumber tmp_num = num - (num / KNumber(400)).integerPart() * KNumber(400); 0133 if (tmp_num < KNumber::Zero) 0134 return tmp_num + KNumber(400); 0135 return tmp_num; 0136 } 0137 0138 KNumber CalcEngine_p::ArcCosDeg(const KNumber &input) 0139 { 0140 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0141 return KNumber::NaN; 0142 } 0143 0144 if (input.type() == KNumber::TYPE_INTEGER) { 0145 if (input == KNumber::One) { 0146 return KNumber::Zero; 0147 } 0148 if (input == -KNumber::One) { 0149 return KNumber(180); 0150 } 0151 if (input == KNumber::Zero) { 0152 return KNumber(90); 0153 } 0154 } 0155 return Rad2Deg(input.acos()); 0156 } 0157 0158 KNumber CalcEngine_p::ArcCosRad(const KNumber &input) 0159 { 0160 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0161 return KNumber::NaN; 0162 } 0163 return input.acos(); 0164 } 0165 0166 KNumber CalcEngine_p::ArcCosGrad(const KNumber &input) 0167 { 0168 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0169 return KNumber::NaN; 0170 } 0171 if (input.type() == KNumber::TYPE_INTEGER) { 0172 if (input == KNumber::One) { 0173 return KNumber::Zero; 0174 } 0175 if (input == -KNumber::One) { 0176 return KNumber(200); 0177 } 0178 if (input == KNumber::Zero) { 0179 return KNumber(100); 0180 } 0181 } 0182 return Rad2Gra(input.acos()); 0183 } 0184 0185 KNumber CalcEngine_p::ArcSinDeg(const KNumber &input) 0186 { 0187 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0188 return KNumber::NaN; 0189 } 0190 if (input.type() == KNumber::TYPE_INTEGER) { 0191 if (input == KNumber::One) { 0192 return KNumber(90); 0193 } 0194 if (input == -KNumber::One) { 0195 return KNumber(-90); 0196 } 0197 if (input == KNumber::Zero) { 0198 return KNumber::Zero; 0199 } 0200 } 0201 return Rad2Deg(input.asin()); 0202 } 0203 0204 KNumber CalcEngine_p::ArcSinRad(const KNumber &input) 0205 { 0206 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0207 return KNumber::NaN; 0208 } 0209 return input.asin(); 0210 } 0211 0212 KNumber CalcEngine_p::ArcSinGrad(const KNumber &input) 0213 { 0214 if (input.type() == KNumber::TYPE_ERROR || input < -KNumber::One || input > KNumber::One) { 0215 return KNumber::NaN; 0216 } 0217 if (input.type() == KNumber::TYPE_INTEGER) { 0218 if (input == KNumber::One) { 0219 return KNumber(100); 0220 } 0221 if (input == -KNumber::One) { 0222 return KNumber(-100); 0223 } 0224 if (input == KNumber::Zero) { 0225 return KNumber::Zero; 0226 } 0227 } 0228 return Rad2Gra(input.asin()); 0229 } 0230 0231 KNumber CalcEngine_p::ArcTangensDeg(const KNumber &input) 0232 { 0233 if (input.type() == KNumber::TYPE_ERROR) { 0234 if (input == KNumber::NaN) 0235 return KNumber::NaN; 0236 if (input == KNumber::PosInfinity) 0237 return KNumber(90); 0238 if (input == KNumber::NegInfinity) 0239 return KNumber(-90); 0240 } 0241 0242 return Rad2Deg(input.atan()); 0243 } 0244 0245 KNumber CalcEngine_p::ArcTangensRad(const KNumber &input) 0246 { 0247 if (input.type() == KNumber::TYPE_ERROR) { 0248 if (input == KNumber::NaN) 0249 return KNumber::NaN; 0250 if (input == KNumber::PosInfinity) 0251 return KNumber::Pi() / KNumber(2); 0252 if (input == KNumber::NegInfinity) 0253 return -KNumber::Pi() / KNumber(2); 0254 } 0255 0256 return input.atan(); 0257 } 0258 0259 KNumber CalcEngine_p::ArcTangensGrad(const KNumber &input) 0260 { 0261 if (input.type() == KNumber::TYPE_ERROR) { 0262 if (input == KNumber::NaN) 0263 return KNumber::NaN; 0264 if (input == KNumber::PosInfinity) 0265 return KNumber(100); 0266 if (input == KNumber::NegInfinity) 0267 return KNumber(-100); 0268 } 0269 0270 return Rad2Gra(input.atan()); 0271 } 0272 0273 KNumber CalcEngine_p::AreaCosHyp(const KNumber &input) 0274 { 0275 if (input.type() == KNumber::TYPE_ERROR) { 0276 if (input == KNumber::NaN) 0277 return KNumber::NaN; 0278 if (input == KNumber::PosInfinity) 0279 return KNumber::PosInfinity; 0280 if (input == KNumber::NegInfinity) 0281 return KNumber::NaN; 0282 } 0283 0284 if (input < KNumber::One) { 0285 return KNumber::NaN; 0286 } 0287 if (input == KNumber::One) { 0288 return KNumber::Zero; 0289 } 0290 return input.acosh(); 0291 } 0292 0293 KNumber CalcEngine_p::AreaSinHyp(const KNumber &input) 0294 { 0295 if (input.type() == KNumber::TYPE_ERROR) { 0296 if (input == KNumber::NaN) 0297 return KNumber::NaN; 0298 if (input == KNumber::PosInfinity) 0299 return KNumber::PosInfinity; 0300 if (input == KNumber::NegInfinity) 0301 return KNumber::NegInfinity; 0302 } 0303 0304 if (input == KNumber::Zero) { 0305 return KNumber::Zero; 0306 } 0307 return input.asinh(); 0308 } 0309 0310 KNumber CalcEngine_p::AreaTangensHyp(const KNumber &input) 0311 { 0312 if (input.type() == KNumber::TYPE_ERROR) { 0313 return KNumber::NaN; 0314 } 0315 0316 if (input < -KNumber::One || input > KNumber::One) { 0317 return KNumber::NaN; 0318 } 0319 if (input == KNumber::One) { 0320 return KNumber::PosInfinity; 0321 } 0322 if (input == -KNumber::One) { 0323 return KNumber::NegInfinity; 0324 } 0325 return input.atanh(); 0326 } 0327 0328 KNumber CalcEngine_p::Complement(const KNumber &input) 0329 { 0330 if (input.type() != KNumber::TYPE_INTEGER) { 0331 return KNumber::NaN; 0332 } 0333 0334 return ~input; 0335 } 0336 0337 KNumber CalcEngine_p::CosDeg(const KNumber &input) 0338 { 0339 if (input.type() == KNumber::TYPE_ERROR) { 0340 return KNumber::NaN; 0341 } 0342 0343 KNumber trunc_input = moveIntoDegInterval(input); 0344 0345 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0346 KNumber mult = trunc_input / KNumber(90); 0347 if (mult.type() == KNumber::TYPE_INTEGER) { 0348 if (mult == KNumber::Zero) 0349 return KNumber::One; 0350 else if (mult == KNumber::One) 0351 return KNumber::Zero; 0352 else if (mult == KNumber(2)) 0353 return KNumber::NegOne; 0354 else if (mult == KNumber(3)) 0355 return KNumber::Zero; 0356 else 0357 return KNumber::NaN; 0358 } 0359 } 0360 0361 trunc_input = Deg2Rad(trunc_input); 0362 return trunc_input.cos(); 0363 } 0364 0365 KNumber CalcEngine_p::CosRad(const KNumber &input) 0366 { 0367 if (input.type() == KNumber::TYPE_ERROR) { 0368 return KNumber::NaN; 0369 } 0370 0371 return input.cos(); 0372 } 0373 0374 KNumber CalcEngine_p::CosGrad(const KNumber &input) 0375 { 0376 if (input.type() == KNumber::TYPE_ERROR) { 0377 return KNumber::NaN; 0378 } 0379 KNumber trunc_input = moveIntoGradInterval(input); 0380 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0381 KNumber mult = trunc_input / KNumber(100); 0382 if (mult.type() == KNumber::TYPE_INTEGER) { 0383 if (mult == KNumber::Zero) 0384 return KNumber::One; 0385 else if (mult == KNumber::One) 0386 return KNumber::Zero; 0387 else if (mult == KNumber(2)) 0388 return KNumber::NegOne; 0389 else if (mult == KNumber(3)) 0390 return KNumber::Zero; 0391 else 0392 return KNumber::NaN; 0393 } 0394 } 0395 trunc_input = Gra2Rad(trunc_input); 0396 0397 return trunc_input.cos(); 0398 } 0399 0400 KNumber CalcEngine_p::CosHyp(const KNumber &input) 0401 { 0402 if (input.type() == KNumber::TYPE_ERROR) { 0403 if (input == KNumber::NaN) 0404 return KNumber::NaN; 0405 if (input == KNumber::PosInfinity) 0406 return KNumber::PosInfinity; 0407 if (input == KNumber::NegInfinity) 0408 return KNumber::PosInfinity; 0409 return KNumber::NaN; 0410 } 0411 0412 return input.cosh(); 0413 } 0414 0415 KNumber CalcEngine_p::Cube(const KNumber &input) 0416 { 0417 return input * input * input; 0418 } 0419 0420 KNumber CalcEngine_p::CubeRoot(const KNumber &input) 0421 { 0422 return input.cbrt(); 0423 } 0424 0425 KNumber CalcEngine_p::Exp(const KNumber &input) 0426 { 0427 if (input.type() == KNumber::TYPE_ERROR) { 0428 if (input == KNumber::NaN) 0429 return KNumber::NaN; 0430 if (input == KNumber::PosInfinity) 0431 return KNumber::PosInfinity; 0432 if (input == KNumber::NegInfinity) 0433 return KNumber::Zero; 0434 return KNumber::NaN; 0435 } 0436 return KNumber::Euler().pow(input); 0437 } 0438 0439 KNumber CalcEngine_p::Exp10(const KNumber &input) 0440 { 0441 if (input.type() == KNumber::TYPE_ERROR) { 0442 if (input == KNumber::NaN) 0443 return KNumber::NaN; 0444 if (input == KNumber::PosInfinity) 0445 return KNumber::PosInfinity; 0446 if (input == KNumber::NegInfinity) 0447 return KNumber::Zero; 0448 return KNumber::NaN; 0449 } 0450 return KNumber(10).pow(input); 0451 } 0452 0453 KNumber CalcEngine_p::Factorial(const KNumber &input) 0454 { 0455 if (input == KNumber::PosInfinity) 0456 return KNumber::PosInfinity; 0457 if (input < KNumber::Zero || input.type() == KNumber::TYPE_ERROR) { 0458 return KNumber::NaN; 0459 } 0460 0461 return input.integerPart().factorial(); 0462 } 0463 0464 KNumber CalcEngine_p::Gamma(const KNumber &input) 0465 { 0466 if (input == KNumber::PosInfinity) 0467 return KNumber::PosInfinity; 0468 if (input < KNumber::Zero || input.type() == KNumber::TYPE_ERROR) { 0469 return KNumber::NaN; 0470 } 0471 0472 return input.tgamma(); 0473 } 0474 0475 KNumber CalcEngine_p::InvertSign(const KNumber &input) 0476 { 0477 return -input; 0478 } 0479 0480 KNumber CalcEngine_p::Ln(const KNumber &input) 0481 { 0482 if (input < KNumber::Zero) 0483 return KNumber::NaN; 0484 else if (input == KNumber::Zero) 0485 return KNumber::NegInfinity; 0486 else if (input == KNumber::One) 0487 return KNumber::Zero; 0488 else { 0489 return input.ln(); 0490 } 0491 } 0492 0493 KNumber CalcEngine_p::Log10(const KNumber &input) 0494 { 0495 if (input < KNumber::Zero) 0496 return KNumber::NaN; 0497 else if (input == KNumber::Zero) 0498 return KNumber::NegInfinity; 0499 else if (input == KNumber::One) 0500 return KNumber::Zero; 0501 else { 0502 return input.log10(); 0503 } 0504 } 0505 0506 KNumber CalcEngine_p::Reciprocal(const KNumber &input) 0507 { 0508 return KNumber::One / input; 0509 } 0510 0511 KNumber CalcEngine_p::SinDeg(const KNumber &input) 0512 { 0513 if (input.type() == KNumber::TYPE_ERROR) { 0514 return KNumber::NaN; 0515 } 0516 0517 KNumber trunc_input = moveIntoDegInterval(input); 0518 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0519 KNumber mult = trunc_input / KNumber(90); 0520 if (mult.type() == KNumber::TYPE_INTEGER) { 0521 if (mult == KNumber::Zero) 0522 return KNumber::Zero; 0523 else if (mult == KNumber::One) 0524 return KNumber::One; 0525 else if (mult == KNumber(2)) 0526 return KNumber::Zero; 0527 else if (mult == KNumber(3)) 0528 return KNumber::NegOne; 0529 else 0530 return KNumber::NaN; 0531 } 0532 } 0533 trunc_input = Deg2Rad(trunc_input); 0534 0535 return trunc_input.sin(); 0536 } 0537 0538 KNumber CalcEngine_p::SinRad(const KNumber &input) 0539 { 0540 if (input.type() == KNumber::TYPE_ERROR) { 0541 return KNumber::NaN; 0542 } 0543 0544 return input.sin(); 0545 } 0546 0547 KNumber CalcEngine_p::SinGrad(const KNumber &input) 0548 { 0549 if (input.type() == KNumber::TYPE_ERROR) { 0550 return KNumber::NaN; 0551 } 0552 0553 KNumber trunc_input = moveIntoGradInterval(input); 0554 if (trunc_input.type() == KNumber::TYPE_INTEGER) { 0555 KNumber mult = trunc_input / KNumber(100); 0556 if (mult.type() == KNumber::TYPE_INTEGER) { 0557 if (mult == KNumber::Zero) 0558 return KNumber::Zero; 0559 else if (mult == KNumber::One) 0560 return KNumber::One; 0561 else if (mult == KNumber(2)) 0562 return KNumber::Zero; 0563 else if (mult == KNumber(3)) 0564 return KNumber::NegOne; 0565 else 0566 return KNumber::NaN; 0567 } 0568 } 0569 0570 trunc_input = Gra2Rad(trunc_input); 0571 0572 return trunc_input.sin(); 0573 } 0574 0575 KNumber CalcEngine_p::SinHyp(const KNumber &input) 0576 { 0577 if (input.type() == KNumber::TYPE_ERROR) { 0578 if (input == KNumber::NaN) 0579 return KNumber::NaN; 0580 if (input == KNumber::PosInfinity) 0581 return KNumber::PosInfinity; 0582 if (input == KNumber::NegInfinity) 0583 return KNumber::NegInfinity; 0584 return KNumber::NaN; 0585 } 0586 0587 return input.sinh(); 0588 } 0589 0590 KNumber CalcEngine_p::Square(const KNumber &input) 0591 { 0592 return input * input; 0593 } 0594 0595 KNumber CalcEngine_p::SquareRoot(const KNumber &input) 0596 { 0597 return input.sqrt(); 0598 } 0599 0600 KNumber CalcEngine_p::Percentage(const KNumber &input) 0601 { 0602 return ExecDivide(input, KNumber::OneHundred); 0603 } 0604 0605 void CalcEngine_p::StatClearAll(const KNumber &input) 0606 { 0607 Q_UNUSED(input); 0608 stats.clearAll(); 0609 } 0610 0611 KNumber CalcEngine_p::StatCount(const KNumber &input) 0612 { 0613 Q_UNUSED(input); 0614 return KNumber(stats.count()); 0615 } 0616 0617 void CalcEngine_p::StatDataNew(const KNumber &input) 0618 { 0619 stats.enterData(input); 0620 } 0621 0622 void CalcEngine_p::StatDataDel(const KNumber &input) 0623 { 0624 Q_UNUSED(input); 0625 stats.clearLast(); 0626 } 0627 0628 KNumber CalcEngine_p::StatMean(const KNumber &input) 0629 { 0630 Q_UNUSED(input); 0631 return stats.mean(); 0632 } 0633 0634 KNumber CalcEngine_p::StatMedian(const KNumber &input) 0635 { 0636 Q_UNUSED(input); 0637 return stats.median(); 0638 } 0639 0640 KNumber CalcEngine_p::StatStdDeviation(const KNumber &input) 0641 { 0642 Q_UNUSED(input); 0643 return stats.std(); 0644 } 0645 0646 KNumber CalcEngine_p::StatStdSample(const KNumber &input) 0647 { 0648 Q_UNUSED(input); 0649 return stats.sample_std(); 0650 } 0651 0652 KNumber CalcEngine_p::StatSum(const KNumber &input) 0653 { 0654 Q_UNUSED(input); 0655 return stats.sum(); 0656 } 0657 0658 KNumber CalcEngine_p::StatSumSquares(const KNumber &input) 0659 { 0660 Q_UNUSED(input); 0661 return stats.sum_of_squares(); 0662 } 0663 0664 KNumber CalcEngine_p::TangensDeg(const KNumber &input) 0665 { 0666 if (input.type() == KNumber::TYPE_ERROR) { 0667 return KNumber::NaN; 0668 } 0669 0670 KNumber arg1 = SinDeg(input); 0671 KNumber arg2 = CosDeg(input); 0672 0673 return arg1 / arg2; 0674 } 0675 0676 KNumber CalcEngine_p::TangensRad(const KNumber &input) 0677 { 0678 if (input.type() == KNumber::TYPE_ERROR) { 0679 return KNumber::NaN; 0680 } 0681 0682 KNumber arg1 = SinRad(input); 0683 KNumber arg2 = CosRad(input); 0684 0685 return arg1 / arg2; 0686 } 0687 0688 KNumber CalcEngine_p::TangensGrad(const KNumber &input) 0689 { 0690 if (input.type() == KNumber::TYPE_ERROR) { 0691 return KNumber::NaN; 0692 } 0693 0694 KNumber arg1 = SinGrad(input); 0695 KNumber arg2 = CosGrad(input); 0696 0697 return arg1 / arg2; 0698 } 0699 0700 KNumber CalcEngine_p::TangensHyp(const KNumber &input) 0701 { 0702 if (input.type() == KNumber::TYPE_ERROR) { 0703 if (input == KNumber::NaN) 0704 return KNumber::NaN; 0705 if (input == KNumber::PosInfinity) 0706 return KNumber::One; 0707 if (input == KNumber::NegInfinity) 0708 return KNumber::NegOne; 0709 return KNumber::NaN; 0710 } 0711 0712 return input.tanh(); 0713 }