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