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