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 }