File indexing completed on 2024-03-24 05:52:53
0001 /* 0002 SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 // clang-format off 0007 #include "config-kcalc.h" 0008 // clang-format on 0009 #include "knumber.h" 0010 #include "knumber_base.h" 0011 #include "knumber_error.h" 0012 #include "knumber_float.h" 0013 #include "knumber_fraction.h" 0014 #include "knumber_integer.h" 0015 #include <QRegExp> 0016 #include <QStringList> 0017 #include <cmath> 0018 0019 QString KNumber::GroupSeparator = QStringLiteral(","); 0020 QString KNumber::DecimalSeparator = QStringLiteral("."); 0021 0022 const KNumber KNumber::Zero(QStringLiteral("0")); 0023 const KNumber KNumber::One(QStringLiteral("1")); 0024 const KNumber KNumber::NegOne(QStringLiteral("-1")); 0025 const KNumber KNumber::OneHundred(QStringLiteral("100")); 0026 const KNumber KNumber::OneThousand(QStringLiteral("1000")); 0027 const KNumber KNumber::PosInfinity(QStringLiteral("inf")); 0028 const KNumber KNumber::NegInfinity(QStringLiteral("-inf")); 0029 const KNumber KNumber::NaN(QStringLiteral("nan")); 0030 0031 namespace 0032 { 0033 namespace impl 0034 { 0035 //------------------------------------------------------------------------------ 0036 // Name: increment 0037 //------------------------------------------------------------------------------ 0038 void increment(QString &str, int position) 0039 { 0040 for (int i = position; i >= 0; i--) { 0041 const char last_char = str[i].toLatin1(); 0042 switch (last_char) { 0043 case '0': 0044 str[i] = QLatin1Char('1'); 0045 break; 0046 case '1': 0047 str[i] = QLatin1Char('2'); 0048 break; 0049 case '2': 0050 str[i] = QLatin1Char('3'); 0051 break; 0052 case '3': 0053 str[i] = QLatin1Char('4'); 0054 break; 0055 case '4': 0056 str[i] = QLatin1Char('5'); 0057 break; 0058 case '5': 0059 str[i] = QLatin1Char('6'); 0060 break; 0061 case '6': 0062 str[i] = QLatin1Char('7'); 0063 break; 0064 case '7': 0065 str[i] = QLatin1Char('8'); 0066 break; 0067 case '8': 0068 str[i] = QLatin1Char('9'); 0069 break; 0070 case '9': 0071 str[i] = QLatin1Char('0'); 0072 if (i == 0) { 0073 str.prepend(QLatin1Char('1')); 0074 } 0075 continue; 0076 case '.': 0077 continue; 0078 } 0079 break; 0080 } 0081 } 0082 0083 //------------------------------------------------------------------------------ 0084 // Name: round 0085 //------------------------------------------------------------------------------ 0086 void round(QString &str, int precision) 0087 { 0088 int decimalSymbolPos = str.indexOf(QLatin1Char('.')); 0089 if (decimalSymbolPos == -1) { 0090 if (precision == 0) { 0091 return; 0092 } else { 0093 str.append(QLatin1Char('.')); 0094 str.append(QString().fill(QLatin1Char('0'), precision)); 0095 return; 0096 } 0097 } else { 0098 int desiredLength = decimalSymbolPos + precision + 1; 0099 int extraZeroNeeded = desiredLength - str.length(); 0100 0101 if (extraZeroNeeded == 0) { 0102 return; 0103 } else if (extraZeroNeeded > 0) { 0104 str.append(QString().fill(QLatin1Char('0'), extraZeroNeeded)); 0105 } else { 0106 // decide whether to round up or down based on the digit after desired length 0107 if (str.at(desiredLength).toLatin1() >= '5') { 0108 increment(str, desiredLength - 1); 0109 } 0110 decimalSymbolPos = str.indexOf(QLatin1Char('.')); 0111 str.truncate(decimalSymbolPos + precision + 1); 0112 } 0113 } 0114 } 0115 } 0116 0117 //------------------------------------------------------------------------------ 0118 // Name: round 0119 //------------------------------------------------------------------------------ 0120 QString round(const QString &s, int precision) 0121 { 0122 QString tmp = s; 0123 if (precision < 0 || !QRegExp(QLatin1String(R"(^[+-]?\d+(\.\d+)*(e[+-]?\d+)?$)")).exactMatch(tmp)) { 0124 return s; 0125 } 0126 0127 // Skip the sign (for now) 0128 const bool neg = (tmp[0] == QLatin1Char('-')); 0129 if (neg || tmp[0] == QLatin1Char('+')) { 0130 tmp.remove(0, 1); 0131 } 0132 0133 // Split off exponential part (including 'e'-symbol) 0134 QString mantString = tmp.section(QLatin1Char('e'), 0, 0, QString::SectionCaseInsensitiveSeps); 0135 QString expString = tmp.section(QLatin1Char('e'), 1, 1, QString::SectionCaseInsensitiveSeps | QString::SectionIncludeLeadingSep); 0136 0137 if (expString.length() == 1) { 0138 expString.clear(); 0139 } 0140 0141 impl::round(mantString, precision); 0142 0143 if (neg) { 0144 mantString.prepend(QLatin1Char('-')); 0145 } 0146 0147 return mantString + expString; 0148 } 0149 } 0150 0151 //------------------------------------------------------------------------------ 0152 // Name: setGroupSeparator 0153 //------------------------------------------------------------------------------ 0154 void KNumber::setGroupSeparator(const QString &ch) 0155 { 0156 GroupSeparator = ch; 0157 } 0158 0159 //------------------------------------------------------------------------------ 0160 // Name: setDecimalSeparator 0161 //------------------------------------------------------------------------------ 0162 void KNumber::setDecimalSeparator(const QString &ch) 0163 { 0164 DecimalSeparator = ch; 0165 } 0166 0167 //------------------------------------------------------------------------------ 0168 // Name: groupSeparator 0169 //------------------------------------------------------------------------------ 0170 QString KNumber::groupSeparator() 0171 { 0172 return GroupSeparator; 0173 } 0174 0175 //------------------------------------------------------------------------------ 0176 // Name: decimalSeparator 0177 //------------------------------------------------------------------------------ 0178 QString KNumber::decimalSeparator() 0179 { 0180 return DecimalSeparator; 0181 } 0182 0183 //------------------------------------------------------------------------------ 0184 // Name: setDefaultFloatPrecision 0185 //------------------------------------------------------------------------------ 0186 void KNumber::setDefaultFloatPrecision(int precision) 0187 { 0188 // Need to transform decimal digits into binary digits 0189 const auto bin_prec = static_cast<unsigned long int>(::ceil(precision * M_LN10 / M_LN2) + 1); 0190 mpfr_set_default_prec(static_cast<mpfr_prec_t>(bin_prec)); 0191 } 0192 0193 //------------------------------------------------------------------------------ 0194 // Name: setSplitoffIntegerForFractionOutput 0195 //------------------------------------------------------------------------------ 0196 void KNumber::setSplitoffIntegerForFractionOutput(bool x) 0197 { 0198 detail::knumber_fraction::set_split_off_integer_for_fraction_output(x); 0199 } 0200 0201 //------------------------------------------------------------------------------ 0202 // Name: setDefaultFractionalInput 0203 //------------------------------------------------------------------------------ 0204 void KNumber::setDefaultFractionalInput(bool x) 0205 { 0206 detail::knumber_fraction::set_default_fractional_input(x); 0207 } 0208 0209 //------------------------------------------------------------------------------ 0210 // Name: setDefaultFloatOutput 0211 //------------------------------------------------------------------------------ 0212 void KNumber::setDefaultFloatOutput(bool x) 0213 { 0214 detail::knumber_fraction::set_default_fractional_output(!x); 0215 } 0216 0217 //------------------------------------------------------------------------------ 0218 // Name: Pi 0219 //------------------------------------------------------------------------------ 0220 KNumber KNumber::Pi() 0221 { 0222 // TODO: after 4.10 release: 0223 // create a new constructor which works just like the normal QString 0224 // accepting constructor, but allows us to specify separator 0225 // characters, this will allow things to be done slightly more 0226 // efficiently 0227 QString s(QStringLiteral("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")); 0228 s.replace(QLatin1Char('.'), DecimalSeparator); 0229 return KNumber(s); 0230 } 0231 0232 //------------------------------------------------------------------------------ 0233 // Name: Euler 0234 //------------------------------------------------------------------------------ 0235 KNumber KNumber::Euler() 0236 { 0237 // TODO: after 4.10 release: 0238 // create a new constructor which works just like the normal QString 0239 // accepting constructor, but allows us to specify separator 0240 // characters, this will allow things to be done slightly more 0241 // efficiently 0242 QString s(QStringLiteral("2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274")); 0243 s.replace(QLatin1Char('.'), DecimalSeparator); 0244 return KNumber(s); 0245 } 0246 0247 //------------------------------------------------------------------------------ 0248 // Name: KNumber 0249 //------------------------------------------------------------------------------ 0250 KNumber::KNumber() 0251 : value_(new detail::knumber_integer(0)) 0252 { 0253 } 0254 0255 //------------------------------------------------------------------------------ 0256 // Name: KNumber 0257 //------------------------------------------------------------------------------ 0258 KNumber::KNumber(const QString &s) 0259 : value_(nullptr) 0260 { 0261 const QRegExp special_regex(QLatin1String("^(inf|-inf|nan)$")); 0262 // const QRegExp integer_regex(QLatin1String("^[+-]?\\d+$")); 0263 const QRegExp integer_regex(QLatin1String("^[+-]?\\[1-9]d+$")); 0264 const QRegExp binary_integer_regex(QLatin1String("^0b[0-1]{1,64}$")); 0265 const QRegExp octal_integer_regex(QLatin1String("^0[0-7]{1,21}$")); 0266 const QRegExp hex_integer_regex(QLatin1String("^0x[0-9A-F]{1,16}$")); 0267 const QRegExp fraction_regex(QLatin1String("^[+-]?\\d+/\\d+$")); 0268 const QRegExp float_regex(QString(QLatin1String(R"(^([+-]?\d*)(%1\d*)?(e([+-]?\d+))?$)")).arg(QRegExp::escape(DecimalSeparator))); 0269 0270 if (special_regex.exactMatch(s)) { 0271 value_ = new detail::knumber_error(s); 0272 } else if (integer_regex.exactMatch(s)) { 0273 value_ = new detail::knumber_integer(s); 0274 } else if (fraction_regex.exactMatch(s)) { 0275 value_ = new detail::knumber_fraction(s); 0276 simplify(); 0277 } else if (hex_integer_regex.exactMatch(s) || octal_integer_regex.exactMatch(s) || binary_integer_regex.exactMatch(s)) { 0278 value_ = new detail::knumber_integer(s.toULongLong(nullptr, 0)); 0279 } else if (float_regex.exactMatch(s)) { 0280 if (detail::knumber_fraction::default_fractional_input) { 0281 const QStringList list = float_regex.capturedTexts(); 0282 if (list.size() == 5) { 0283 const QString ipart = list[1]; 0284 const QString fpart = list[2]; 0285 const int e_val = list[4].toInt(); 0286 0287 QString num = ipart + fpart.mid(1); 0288 QString den = QLatin1String("1") + QString(fpart.size() - 1, QLatin1Char('0')); 0289 0290 if (e_val < 0) { 0291 den = den + QString(::abs(e_val), QLatin1Char('0')); 0292 } else if (e_val > 0) { 0293 num = num + QString(::abs(e_val), QLatin1Char('0')); 0294 } 0295 0296 value_ = new detail::knumber_fraction(QStringLiteral("%1/%2").arg(num, den)); 0297 simplify(); 0298 return; 0299 } 0300 } 0301 0302 // we need to normalize the decimal separator to US style because that's 0303 // the only type that the GMP function accept 0304 QString new_s = s; 0305 new_s.replace(DecimalSeparator, QLatin1String(".")); 0306 0307 value_ = new detail::knumber_float(new_s); 0308 simplify(); 0309 } else { 0310 value_ = new detail::knumber_error(detail::knumber_error::ERROR_UNDEFINED); 0311 } 0312 } 0313 0314 //------------------------------------------------------------------------------ 0315 // Name: KNumber 0316 //------------------------------------------------------------------------------ 0317 KNumber::KNumber(qint32 value) 0318 : value_(new detail::knumber_integer(value)) 0319 { 0320 } 0321 0322 //------------------------------------------------------------------------------ 0323 // Name: KNumber 0324 //------------------------------------------------------------------------------ 0325 KNumber::KNumber(qint64 value) 0326 : value_(new detail::knumber_integer(value)) 0327 { 0328 } 0329 0330 //------------------------------------------------------------------------------ 0331 // Name: KNumber 0332 //------------------------------------------------------------------------------ 0333 KNumber::KNumber(quint32 value) 0334 : value_(new detail::knumber_integer(value)) 0335 { 0336 } 0337 0338 //------------------------------------------------------------------------------ 0339 // Name: KNumber 0340 //------------------------------------------------------------------------------ 0341 KNumber::KNumber(quint64 value) 0342 : value_(new detail::knumber_integer(value)) 0343 { 0344 } 0345 0346 //------------------------------------------------------------------------------ 0347 // Name: KNumber 0348 //------------------------------------------------------------------------------ 0349 KNumber::KNumber(qint64 num, quint64 den) 0350 : value_(new detail::knumber_fraction(num, den)) 0351 { 0352 } 0353 0354 //------------------------------------------------------------------------------ 0355 // Name: KNumber 0356 //------------------------------------------------------------------------------ 0357 KNumber::KNumber(quint64 num, quint64 den) 0358 : value_(new detail::knumber_fraction(num, den)) 0359 { 0360 } 0361 0362 #ifdef HAVE_LONG_DOUBLE 0363 //------------------------------------------------------------------------------ 0364 // Name: KNumber 0365 //------------------------------------------------------------------------------ 0366 KNumber::KNumber(long double value) 0367 : value_(new detail::knumber_float(value)) 0368 { 0369 simplify(); 0370 } 0371 #endif 0372 0373 //------------------------------------------------------------------------------ 0374 // Name: KNumber 0375 //------------------------------------------------------------------------------ 0376 KNumber::KNumber(double value) 0377 : value_(new detail::knumber_float(value)) 0378 { 0379 simplify(); 0380 } 0381 0382 //------------------------------------------------------------------------------ 0383 // Name: KNumber 0384 //------------------------------------------------------------------------------ 0385 KNumber::KNumber(const KNumber &other) 0386 : value_(nullptr) 0387 { 0388 if (&other != this) { 0389 value_ = other.value_->clone(); 0390 } 0391 } 0392 0393 //------------------------------------------------------------------------------ 0394 // Name: ~KNumber 0395 //------------------------------------------------------------------------------ 0396 KNumber::~KNumber() 0397 { 0398 delete value_; 0399 } 0400 0401 //------------------------------------------------------------------------------ 0402 // Name: type 0403 //------------------------------------------------------------------------------ 0404 KNumber::Type KNumber::type() const 0405 { 0406 if (dynamic_cast<detail::knumber_integer *>(value_)) { 0407 return TYPE_INTEGER; 0408 } else if (dynamic_cast<detail::knumber_float *>(value_)) { 0409 return TYPE_FLOAT; 0410 } else if (dynamic_cast<detail::knumber_fraction *>(value_)) { 0411 return TYPE_FRACTION; 0412 } else if (dynamic_cast<detail::knumber_error *>(value_)) { 0413 return TYPE_ERROR; 0414 } else { 0415 Q_ASSERT(0); 0416 return TYPE_ERROR; 0417 } 0418 } 0419 0420 //------------------------------------------------------------------------------ 0421 // Name: operator= 0422 //------------------------------------------------------------------------------ 0423 KNumber &KNumber::operator=(const KNumber &rhs) 0424 { 0425 KNumber(rhs).swap(*this); 0426 return *this; 0427 } 0428 0429 //------------------------------------------------------------------------------ 0430 // Name: swap 0431 //------------------------------------------------------------------------------ 0432 void KNumber::swap(KNumber &other) 0433 { 0434 qSwap(value_, other.value_); 0435 } 0436 0437 //------------------------------------------------------------------------------ 0438 // Name: integerPart 0439 //------------------------------------------------------------------------------ 0440 KNumber KNumber::integerPart() const 0441 { 0442 KNumber x(*this); 0443 0444 if (auto const p = dynamic_cast<detail::knumber_integer *>(value_)) { 0445 // NO-OP 0446 Q_UNUSED(p); 0447 } else if (auto const p = dynamic_cast<detail::knumber_float *>(value_)) { 0448 detail::knumber_base *v = new detail::knumber_integer(p); 0449 qSwap(v, x.value_); 0450 delete v; 0451 } else if (auto const p = dynamic_cast<detail::knumber_fraction *>(value_)) { 0452 detail::knumber_base *v = new detail::knumber_integer(p); 0453 qSwap(v, x.value_); 0454 delete v; 0455 } else if (auto const p = dynamic_cast<detail::knumber_error *>(value_)) { 0456 // NO-OP 0457 Q_UNUSED(p); 0458 } else { 0459 Q_ASSERT(0); 0460 } 0461 0462 return x; 0463 } 0464 0465 //------------------------------------------------------------------------------ 0466 // Name: simplify 0467 //------------------------------------------------------------------------------ 0468 void KNumber::simplify() 0469 { 0470 if (value_->is_integer()) { 0471 if (auto const p = dynamic_cast<detail::knumber_integer *>(value_)) { 0472 // NO-OP 0473 Q_UNUSED(p); 0474 } else if (auto const p = dynamic_cast<detail::knumber_float *>(value_)) { 0475 detail::knumber_base *v = new detail::knumber_integer(p); 0476 qSwap(v, value_); 0477 delete v; 0478 } else if (auto const p = dynamic_cast<detail::knumber_fraction *>(value_)) { 0479 detail::knumber_base *v = new detail::knumber_integer(p); 0480 qSwap(v, value_); 0481 delete v; 0482 } else if (auto const p = dynamic_cast<detail::knumber_error *>(value_)) { 0483 // NO-OP 0484 Q_UNUSED(p); 0485 } else { 0486 Q_ASSERT(0); 0487 } 0488 } 0489 } 0490 0491 //------------------------------------------------------------------------------ 0492 // Name: operator+= 0493 //------------------------------------------------------------------------------ 0494 KNumber &KNumber::operator+=(const KNumber &rhs) 0495 { 0496 value_ = value_->add(rhs.value_); 0497 simplify(); 0498 return *this; 0499 } 0500 0501 //------------------------------------------------------------------------------ 0502 // Name: operator-= 0503 //------------------------------------------------------------------------------ 0504 KNumber &KNumber::operator-=(const KNumber &rhs) 0505 { 0506 value_ = value_->sub(rhs.value_); 0507 simplify(); 0508 return *this; 0509 } 0510 0511 //------------------------------------------------------------------------------ 0512 // Name: operator*= 0513 //------------------------------------------------------------------------------ 0514 KNumber &KNumber::operator*=(const KNumber &rhs) 0515 { 0516 value_ = value_->mul(rhs.value_); 0517 simplify(); 0518 return *this; 0519 } 0520 0521 //------------------------------------------------------------------------------ 0522 // Name: operator/= 0523 //------------------------------------------------------------------------------ 0524 KNumber &KNumber::operator/=(const KNumber &rhs) 0525 { 0526 // Fix for bug #330577, x/0 is undefined, not infinity 0527 // Also indirectly fixes bug #329897, tan(90) is undefined, not infinity 0528 if (rhs == Zero) { 0529 *this = NaN; 0530 return *this; 0531 } 0532 0533 value_ = value_->div(rhs.value_); 0534 simplify(); 0535 return *this; 0536 } 0537 0538 //------------------------------------------------------------------------------ 0539 // Name: operator%= 0540 //------------------------------------------------------------------------------ 0541 KNumber &KNumber::operator%=(const KNumber &rhs) 0542 { 0543 value_ = value_->mod(rhs.value_); 0544 simplify(); 0545 return *this; 0546 } 0547 0548 //------------------------------------------------------------------------------ 0549 // Name: operator&= 0550 //------------------------------------------------------------------------------ 0551 KNumber &KNumber::operator&=(const KNumber &rhs) 0552 { 0553 value_ = value_->bitwise_and(rhs.value_); 0554 return *this; 0555 } 0556 0557 //------------------------------------------------------------------------------ 0558 // Name: operator|= 0559 //------------------------------------------------------------------------------ 0560 KNumber &KNumber::operator|=(const KNumber &rhs) 0561 { 0562 value_ = value_->bitwise_or(rhs.value_); 0563 return *this; 0564 } 0565 0566 //------------------------------------------------------------------------------ 0567 // Name: operator^= 0568 //------------------------------------------------------------------------------ 0569 KNumber &KNumber::operator^=(const KNumber &rhs) 0570 { 0571 value_ = value_->bitwise_xor(rhs.value_); 0572 return *this; 0573 } 0574 0575 //------------------------------------------------------------------------------ 0576 // Name: operator<< 0577 //------------------------------------------------------------------------------ 0578 KNumber &KNumber::operator<<=(const KNumber &rhs) 0579 { 0580 value_ = value_->bitwise_shift(rhs.value_); 0581 return *this; 0582 } 0583 0584 //------------------------------------------------------------------------------ 0585 // Name: operator>>= 0586 //------------------------------------------------------------------------------ 0587 KNumber &KNumber::operator>>=(const KNumber &rhs) 0588 { 0589 const KNumber rhs_neg(-rhs); 0590 value_ = value_->bitwise_shift(rhs_neg.value_); 0591 return *this; 0592 } 0593 0594 //------------------------------------------------------------------------------ 0595 // Name: operator- 0596 //------------------------------------------------------------------------------ 0597 KNumber KNumber::operator-() const 0598 { 0599 KNumber x(*this); 0600 x.value_ = x.value_->neg(); 0601 return x; 0602 } 0603 0604 //------------------------------------------------------------------------------ 0605 // Name: operator~ 0606 //------------------------------------------------------------------------------ 0607 KNumber KNumber::operator~() const 0608 { 0609 KNumber x(*this); 0610 x.value_ = x.value_->cmp(); 0611 return x; 0612 } 0613 0614 //------------------------------------------------------------------------------ 0615 // Name: toQString 0616 //------------------------------------------------------------------------------ 0617 QString KNumber::toQString(int width, int precision) const 0618 { 0619 if (value_->is_zero()) { 0620 return QStringLiteral("0"); 0621 } 0622 0623 QString s; 0624 0625 if (auto const p = dynamic_cast<detail::knumber_integer *>(value_)) { 0626 if (width > 0) { 0627 s = detail::knumber_float(p).toString(width); 0628 } else { 0629 s = value_->toString(width); 0630 } 0631 } else if (dynamic_cast<detail::knumber_float *>(value_)) { 0632 if (width > 0) { 0633 s = value_->toString(width); 0634 } else { 0635 s = value_->toString(3 * mpf_get_default_prec() / 10); 0636 } 0637 } else if (dynamic_cast<detail::knumber_fraction *>(value_)) { 0638 s = value_->toString(width); 0639 } else { 0640 return value_->toString(width); 0641 } 0642 0643 // now do some rounding to make sure things are displayed reasonably 0644 if (precision >= 0) { 0645 return round(s, precision); 0646 } else { 0647 return s; 0648 } 0649 } 0650 0651 //------------------------------------------------------------------------------ 0652 // Name: toUint64 0653 //------------------------------------------------------------------------------ 0654 quint64 KNumber::toUint64() const 0655 { 0656 return value_->toUint64(); 0657 } 0658 0659 //------------------------------------------------------------------------------ 0660 // Name: toInt64 0661 //------------------------------------------------------------------------------ 0662 qint64 KNumber::toInt64() const 0663 { 0664 return value_->toInt64(); 0665 } 0666 0667 //------------------------------------------------------------------------------ 0668 // Name: abs 0669 //------------------------------------------------------------------------------ 0670 KNumber KNumber::abs() const 0671 { 0672 KNumber z(*this); 0673 z.value_ = z.value_->abs(); 0674 z.simplify(); 0675 return z; 0676 } 0677 0678 //------------------------------------------------------------------------------ 0679 // Name: cbrt 0680 //------------------------------------------------------------------------------ 0681 KNumber KNumber::cbrt() const 0682 { 0683 KNumber z(*this); 0684 z.value_ = z.value_->cbrt(); 0685 z.simplify(); 0686 return z; 0687 } 0688 0689 //------------------------------------------------------------------------------ 0690 // Name: sqrt 0691 //------------------------------------------------------------------------------ 0692 KNumber KNumber::sqrt() const 0693 { 0694 KNumber z(*this); 0695 z.value_ = z.value_->sqrt(); 0696 z.simplify(); 0697 return z; 0698 } 0699 0700 //------------------------------------------------------------------------------ 0701 // Name: pow 0702 //------------------------------------------------------------------------------ 0703 KNumber KNumber::pow(const KNumber &x) const 0704 { 0705 // Fix for bug #330711, pow(0, -x) was causing crashes 0706 // Fix for bug #330597, pow(0,0) was 1 now it is NaN 0707 // Thanks to Raushan Kumar for identifying the issue and submitting 0708 // patches 0709 if (*this == Zero && x <= Zero) { 0710 return NaN; 0711 } 0712 0713 // if the LHS is a special then we can use this function 0714 // no matter what, cause the result is a special too 0715 if (!dynamic_cast<detail::knumber_error *>(value_)) { 0716 // number much bigger than this tend to crash GMP with 0717 // an abort 0718 if (x > KNumber(QStringLiteral("1000000000"))) { 0719 return PosInfinity; 0720 } 0721 } 0722 0723 KNumber z(*this); 0724 z.value_ = z.value_->pow(x.value_); 0725 z.simplify(); 0726 return z; 0727 } 0728 0729 //------------------------------------------------------------------------------ 0730 // Name: sin 0731 //------------------------------------------------------------------------------ 0732 KNumber KNumber::sin() const 0733 { 0734 KNumber z(*this); 0735 z.value_ = z.value_->sin(); 0736 z.simplify(); 0737 return z; 0738 } 0739 0740 //------------------------------------------------------------------------------ 0741 // Name: cos 0742 //------------------------------------------------------------------------------ 0743 KNumber KNumber::cos() const 0744 { 0745 KNumber z(*this); 0746 z.value_ = z.value_->cos(); 0747 z.simplify(); 0748 return z; 0749 } 0750 0751 //------------------------------------------------------------------------------ 0752 // Name: tan 0753 //------------------------------------------------------------------------------ 0754 KNumber KNumber::tan() const 0755 { 0756 KNumber z(*this); 0757 z.value_ = z.value_->tan(); 0758 z.simplify(); 0759 return z; 0760 } 0761 0762 //------------------------------------------------------------------------------ 0763 // Name: tgamma 0764 //------------------------------------------------------------------------------ 0765 KNumber KNumber::tgamma() const 0766 { 0767 KNumber z(*this); 0768 if (z > KNumber(QStringLiteral("10000000000"))) { 0769 return PosInfinity; 0770 } 0771 z.value_ = z.value_->tgamma(); 0772 z.simplify(); 0773 return z; 0774 } 0775 0776 //------------------------------------------------------------------------------ 0777 // Name: asin 0778 //------------------------------------------------------------------------------ 0779 KNumber KNumber::asin() const 0780 { 0781 KNumber z(*this); 0782 z.value_ = z.value_->asin(); 0783 z.simplify(); 0784 return z; 0785 } 0786 0787 //------------------------------------------------------------------------------ 0788 // Name: acos 0789 //------------------------------------------------------------------------------ 0790 KNumber KNumber::acos() const 0791 { 0792 KNumber z(*this); 0793 z.value_ = z.value_->acos(); 0794 z.simplify(); 0795 return z; 0796 } 0797 0798 //------------------------------------------------------------------------------ 0799 // Name: atan 0800 //------------------------------------------------------------------------------ 0801 KNumber KNumber::atan() const 0802 { 0803 KNumber z(*this); 0804 z.value_ = z.value_->atan(); 0805 z.simplify(); 0806 return z; 0807 } 0808 0809 //------------------------------------------------------------------------------ 0810 // Name: sinh 0811 //------------------------------------------------------------------------------ 0812 KNumber KNumber::sinh() const 0813 { 0814 KNumber z(*this); 0815 z.value_ = z.value_->sinh(); 0816 z.simplify(); 0817 return z; 0818 } 0819 0820 //------------------------------------------------------------------------------ 0821 // Name: cosh 0822 //------------------------------------------------------------------------------ 0823 KNumber KNumber::cosh() const 0824 { 0825 KNumber z(*this); 0826 z.value_ = z.value_->cosh(); 0827 z.simplify(); 0828 return z; 0829 } 0830 0831 //------------------------------------------------------------------------------ 0832 // Name: tanh 0833 //------------------------------------------------------------------------------ 0834 KNumber KNumber::tanh() const 0835 { 0836 KNumber z(*this); 0837 z.value_ = z.value_->tanh(); 0838 z.simplify(); 0839 return z; 0840 } 0841 0842 //------------------------------------------------------------------------------ 0843 // Name: asinh 0844 //------------------------------------------------------------------------------ 0845 KNumber KNumber::asinh() const 0846 { 0847 KNumber z(*this); 0848 z.value_ = z.value_->asinh(); 0849 z.simplify(); 0850 return z; 0851 } 0852 0853 //------------------------------------------------------------------------------ 0854 // Name: acosh 0855 //------------------------------------------------------------------------------ 0856 KNumber KNumber::acosh() const 0857 { 0858 KNumber z(*this); 0859 z.value_ = z.value_->acosh(); 0860 z.simplify(); 0861 return z; 0862 } 0863 0864 //------------------------------------------------------------------------------ 0865 // Name: atanh 0866 //------------------------------------------------------------------------------ 0867 KNumber KNumber::atanh() const 0868 { 0869 KNumber z(*this); 0870 z.value_ = z.value_->atanh(); 0871 z.simplify(); 0872 return z; 0873 } 0874 0875 //------------------------------------------------------------------------------ 0876 // Name: factorial 0877 //------------------------------------------------------------------------------ 0878 KNumber KNumber::factorial() const 0879 { 0880 KNumber z(*this); 0881 0882 // number much bigger than this tend to crash GMP with 0883 // an abort 0884 if (z > KNumber(QStringLiteral("10000000000"))) { 0885 return PosInfinity; 0886 } 0887 0888 z.value_ = z.value_->factorial(); 0889 z.simplify(); 0890 return z; 0891 } 0892 0893 //------------------------------------------------------------------------------ 0894 // Name: log2 0895 //------------------------------------------------------------------------------ 0896 KNumber KNumber::log2() const 0897 { 0898 KNumber z(*this); 0899 z.value_ = z.value_->log2(); 0900 z.simplify(); 0901 return z; 0902 } 0903 0904 //------------------------------------------------------------------------------ 0905 // Name: log10 0906 //------------------------------------------------------------------------------ 0907 KNumber KNumber::log10() const 0908 { 0909 KNumber z(*this); 0910 z.value_ = z.value_->log10(); 0911 z.simplify(); 0912 return z; 0913 } 0914 0915 //------------------------------------------------------------------------------ 0916 // Name: ln 0917 //------------------------------------------------------------------------------ 0918 KNumber KNumber::ln() const 0919 { 0920 KNumber z(*this); 0921 z.value_ = z.value_->ln(); 0922 z.simplify(); 0923 return z; 0924 } 0925 0926 //------------------------------------------------------------------------------ 0927 // Name: floor 0928 //------------------------------------------------------------------------------ 0929 KNumber KNumber::floor() const 0930 { 0931 KNumber z(*this); 0932 z.value_ = z.value_->floor(); 0933 z.simplify(); 0934 return z; 0935 } 0936 0937 //------------------------------------------------------------------------------ 0938 // Name: ceil 0939 //------------------------------------------------------------------------------ 0940 KNumber KNumber::ceil() const 0941 { 0942 KNumber z(*this); 0943 z.value_ = z.value_->ceil(); 0944 z.simplify(); 0945 return z; 0946 } 0947 0948 //------------------------------------------------------------------------------ 0949 // Name: exp2 0950 //------------------------------------------------------------------------------ 0951 KNumber KNumber::exp2() const 0952 { 0953 KNumber z(*this); 0954 z.value_ = z.value_->exp2(); 0955 z.simplify(); 0956 return z; 0957 } 0958 0959 //------------------------------------------------------------------------------ 0960 // Name: exp10 0961 //------------------------------------------------------------------------------ 0962 KNumber KNumber::exp10() const 0963 { 0964 KNumber z(*this); 0965 z.value_ = z.value_->exp10(); 0966 z.simplify(); 0967 return z; 0968 } 0969 0970 //------------------------------------------------------------------------------ 0971 // Name: exp 0972 //------------------------------------------------------------------------------ 0973 KNumber KNumber::exp() const 0974 { 0975 KNumber z(*this); 0976 z.value_ = z.value_->exp(); 0977 z.simplify(); 0978 return z; 0979 } 0980 0981 //------------------------------------------------------------------------------ 0982 // Name: bin 0983 //------------------------------------------------------------------------------ 0984 KNumber KNumber::bin(const KNumber &x) const 0985 { 0986 KNumber z(*this); 0987 z.value_ = z.value_->bin(x.value_); 0988 z.simplify(); 0989 return z; 0990 }