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 }