File indexing completed on 2024-04-21 05:50:03

0001 /*
0002     SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "knumber_integer.h"
0008 #include "knumber_error.h"
0009 #include "knumber_float.h"
0010 #include "knumber_fraction.h"
0011 #include <QScopedArrayPointer>
0012 #include <config-kcalc.h>
0013 
0014 namespace detail
0015 {
0016 //------------------------------------------------------------------------------
0017 // Name: knumber_integer
0018 //------------------------------------------------------------------------------
0019 knumber_integer::knumber_integer(const QString &s)
0020 {
0021     mpz_init(mpz_);
0022     mpz_set_str(mpz_, s.toLatin1().constData(), 10);
0023 }
0024 
0025 //------------------------------------------------------------------------------
0026 // Name: knumber_integer
0027 //------------------------------------------------------------------------------
0028 knumber_integer::knumber_integer(qint32 value)
0029 {
0030     mpz_init_set_si(mpz_, static_cast<signed long int>(value));
0031 }
0032 
0033 //------------------------------------------------------------------------------
0034 // Name: knumber_integer
0035 //------------------------------------------------------------------------------
0036 knumber_integer::knumber_integer(qint64 value)
0037 {
0038     mpz_init(mpz_);
0039 #if SIZEOF_SIGNED_LONG == 8
0040     mpz_set_si(mpz_, static_cast<signed long int>(value));
0041 #elif SIZEOF_SIGNED_LONG == 4
0042     mpz_set_si(mpz_, static_cast<signed long int>(value >> 32));
0043     mpz_mul_2exp(mpz_, mpz_, 32);
0044     mpz_add_ui(mpz_, mpz_, static_cast<signed long int>(value));
0045 #else
0046 #error "SIZEOF_SIGNED_LONG is a unhandled case"
0047 #endif
0048 }
0049 
0050 //------------------------------------------------------------------------------
0051 // Name: knumber_integer
0052 //------------------------------------------------------------------------------
0053 knumber_integer::knumber_integer(quint32 value)
0054 {
0055     mpz_init_set_ui(mpz_, static_cast<unsigned long int>(value));
0056 }
0057 
0058 //------------------------------------------------------------------------------
0059 // Name: knumber_integer
0060 //------------------------------------------------------------------------------
0061 knumber_integer::knumber_integer(quint64 value)
0062 {
0063     mpz_init(mpz_);
0064 #if SIZEOF_UNSIGNED_LONG == 8
0065     mpz_set_ui(mpz_, static_cast<unsigned long int>(value));
0066 #elif SIZEOF_UNSIGNED_LONG == 4
0067     mpz_set_ui(mpz_, static_cast<unsigned long int>(value >> 32));
0068     mpz_mul_2exp(mpz_, mpz_, 32);
0069     mpz_add_ui(mpz_, mpz_, static_cast<unsigned long int>(value));
0070 #else
0071 #error "SIZEOF_UNSIGNED_LONG is a unhandled case"
0072 #endif
0073 }
0074 
0075 //------------------------------------------------------------------------------
0076 // Name: knumber_integer
0077 //------------------------------------------------------------------------------
0078 knumber_integer::knumber_integer(mpz_t mpz)
0079 {
0080     mpz_init_set(mpz_, mpz);
0081 }
0082 
0083 //------------------------------------------------------------------------------
0084 // Name: knumber_integer
0085 //------------------------------------------------------------------------------
0086 knumber_integer::knumber_integer(const knumber_integer *value)
0087 {
0088     mpz_init_set(mpz_, value->mpz_);
0089 }
0090 
0091 //------------------------------------------------------------------------------
0092 // Name: knumber_integer
0093 //------------------------------------------------------------------------------
0094 knumber_integer::knumber_integer(const knumber_float *value)
0095 {
0096     mpz_init(mpz_);
0097 
0098     mpf_t mpf;
0099     mpf_init(mpf);
0100 
0101     mpfr_get_f(mpf, value->mpfr_, knumber_float::rounding_mode);
0102     mpz_set_f(mpz_, mpf);
0103 
0104     mpf_clear(mpf);
0105 }
0106 
0107 //------------------------------------------------------------------------------
0108 // Name: knumber_integer
0109 //------------------------------------------------------------------------------
0110 knumber_integer::knumber_integer(const knumber_fraction *value)
0111 {
0112     mpz_init(mpz_);
0113     mpz_set_q(mpz_, value->mpq_);
0114 }
0115 
0116 //------------------------------------------------------------------------------
0117 // Name: clone
0118 //------------------------------------------------------------------------------
0119 knumber_base *knumber_integer::clone()
0120 {
0121     return new knumber_integer(this);
0122 }
0123 
0124 //------------------------------------------------------------------------------
0125 // Name: ~knumber_integer
0126 //------------------------------------------------------------------------------
0127 knumber_integer::~knumber_integer()
0128 {
0129     mpz_clear(mpz_);
0130 }
0131 
0132 //------------------------------------------------------------------------------
0133 // Name: add
0134 //------------------------------------------------------------------------------
0135 knumber_base *knumber_integer::add(knumber_base *rhs)
0136 {
0137     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0138         mpz_add(mpz_, mpz_, p->mpz_);
0139         return this;
0140     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0141         auto const f = new knumber_float(this);
0142         delete this;
0143         return f->add(p);
0144     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0145         auto const q = new knumber_fraction(this);
0146         delete this;
0147         return q->add(p);
0148     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0149         delete this;
0150         return p->clone();
0151     }
0152 
0153     Q_ASSERT(0);
0154     return nullptr;
0155 }
0156 
0157 //------------------------------------------------------------------------------
0158 // Name: sub
0159 //------------------------------------------------------------------------------
0160 knumber_base *knumber_integer::sub(knumber_base *rhs)
0161 {
0162     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0163         mpz_sub(mpz_, mpz_, p->mpz_);
0164         return this;
0165     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0166         auto f = new knumber_float(this);
0167         delete this;
0168         return f->sub(p);
0169     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0170         auto q = new knumber_fraction(this);
0171         delete this;
0172         return q->sub(p);
0173     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0174         knumber_base *e = p->clone();
0175         delete this;
0176         return e->neg();
0177     }
0178 
0179     Q_ASSERT(0);
0180     return nullptr;
0181 }
0182 
0183 //------------------------------------------------------------------------------
0184 // Name: mul
0185 //------------------------------------------------------------------------------
0186 knumber_base *knumber_integer::mul(knumber_base *rhs)
0187 {
0188     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0189         mpz_mul(mpz_, mpz_, p->mpz_);
0190         return this;
0191     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0192         auto f = new knumber_float(this);
0193         delete this;
0194         return f->mul(p);
0195     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0196         auto q = new knumber_fraction(this);
0197         delete this;
0198         return q->mul(p);
0199     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0200         if (is_zero()) {
0201             delete this;
0202             auto e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0203             return e->neg();
0204         }
0205 
0206         if (sign() < 0) {
0207             delete this;
0208             knumber_base *e = p->clone();
0209             return e->neg();
0210         } else {
0211             delete this;
0212             return p->clone();
0213         }
0214     }
0215 
0216     Q_ASSERT(0);
0217     return nullptr;
0218 }
0219 
0220 //------------------------------------------------------------------------------
0221 // Name: div
0222 //------------------------------------------------------------------------------
0223 knumber_base *knumber_integer::div(knumber_base *rhs)
0224 {
0225     if (rhs->is_zero()) {
0226         if (sign() < 0) {
0227             delete this;
0228             return new knumber_error(knumber_error::ERROR_NEG_INFINITY);
0229         } else {
0230             delete this;
0231             return new knumber_error(knumber_error::ERROR_POS_INFINITY);
0232         }
0233     }
0234 
0235     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0236         auto q = new knumber_fraction(this);
0237         delete this;
0238         return q->div(p);
0239     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0240         auto f = new knumber_float(this);
0241         delete this;
0242         return f->div(p);
0243     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0244         auto q = new knumber_fraction(this);
0245         delete this;
0246         return q->div(p);
0247     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0248         if (p->sign() > 0) {
0249             delete this;
0250             return new knumber_integer(0);
0251         } else if (p->sign() < 0) {
0252             delete this;
0253             return new knumber_integer(0);
0254         }
0255 
0256         delete this;
0257         return p->clone();
0258     }
0259 
0260     Q_ASSERT(0);
0261     return nullptr;
0262 }
0263 
0264 //------------------------------------------------------------------------------
0265 // Name: mod
0266 //------------------------------------------------------------------------------
0267 knumber_base *knumber_integer::mod(knumber_base *rhs)
0268 {
0269     if (rhs->is_zero()) {
0270         delete this;
0271         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0272     }
0273 
0274     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0275         mpz_mod(mpz_, mpz_, p->mpz_);
0276         return this;
0277     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0278         auto f = new knumber_float(this);
0279         delete this;
0280         return f->mod(p);
0281     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0282         auto q = new knumber_fraction(this);
0283         delete this;
0284         return q->mod(p);
0285     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0286         delete this;
0287         return p->clone();
0288     }
0289 
0290     Q_ASSERT(0);
0291     return nullptr;
0292 }
0293 
0294 //------------------------------------------------------------------------------
0295 // Name: bitwise_and
0296 //------------------------------------------------------------------------------
0297 knumber_base *knumber_integer::bitwise_and(knumber_base *rhs)
0298 {
0299     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0300         mpz_and(mpz_, mpz_, p->mpz_);
0301         return this;
0302     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0303         auto f = new knumber_float(this);
0304         delete this;
0305         return f->bitwise_and(p);
0306     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0307         auto f = new knumber_fraction(this);
0308         delete this;
0309         return f->bitwise_and(p);
0310     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0311         delete this;
0312         return p->clone();
0313     }
0314 
0315     Q_ASSERT(0);
0316     return nullptr;
0317 }
0318 
0319 //------------------------------------------------------------------------------
0320 // Name: bitwise_xor
0321 //------------------------------------------------------------------------------
0322 knumber_base *knumber_integer::bitwise_xor(knumber_base *rhs)
0323 {
0324     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0325         mpz_xor(mpz_, mpz_, p->mpz_);
0326         return this;
0327     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0328         auto f = new knumber_float(this);
0329         delete this;
0330         return f->bitwise_xor(p);
0331     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0332         auto f = new knumber_fraction(this);
0333         delete this;
0334         return f->bitwise_xor(p);
0335     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0336         delete this;
0337         return p->clone();
0338     }
0339 
0340     Q_ASSERT(0);
0341     return nullptr;
0342 }
0343 
0344 //------------------------------------------------------------------------------
0345 // Name: bitwise_or
0346 //------------------------------------------------------------------------------
0347 knumber_base *knumber_integer::bitwise_or(knumber_base *rhs)
0348 {
0349     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0350         mpz_ior(mpz_, mpz_, p->mpz_);
0351         return this;
0352     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0353         auto f = new knumber_float(this);
0354         delete this;
0355         return f->bitwise_or(p);
0356     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0357         auto f = new knumber_fraction(this);
0358         delete this;
0359         return f->bitwise_or(p);
0360     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0361         delete this;
0362         return p->clone();
0363     }
0364 
0365     Q_ASSERT(0);
0366     return nullptr;
0367 }
0368 
0369 //------------------------------------------------------------------------------
0370 // Name: bitwise_shift
0371 //------------------------------------------------------------------------------
0372 knumber_base *knumber_integer::bitwise_shift(knumber_base *rhs)
0373 {
0374     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0375         const signed long int bit_count = mpz_get_si(p->mpz_);
0376 
0377         // TODO: left shift with high bit set is broken in
0378         //       non decimal modes :-/, always displays 0
0379         //       interestingly, the bit is not "lost"
0380         //       we simply don't have a mechanism to display
0381         //       values in HEX/DEC/OCT mode which are greater than
0382         //       64-bits
0383 
0384         if (bit_count > 0) {
0385             // left shift
0386             mpz_mul_2exp(mpz_, mpz_, bit_count);
0387         } else if (bit_count < 0) {
0388             // right shift
0389             if (mpz_sgn(mpz_) < 0) {
0390                 mpz_fdiv_q_2exp(mpz_, mpz_, -bit_count);
0391             } else {
0392                 mpz_tdiv_q_2exp(mpz_, mpz_, -bit_count);
0393             }
0394         }
0395         return this;
0396     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0397         Q_UNUSED(p);
0398         auto e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0399         delete this;
0400         return e;
0401     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0402         Q_UNUSED(p);
0403         auto e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0404         delete this;
0405         return e;
0406     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0407         Q_UNUSED(p);
0408         auto e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0409         delete this;
0410         return e;
0411     }
0412 
0413     Q_ASSERT(0);
0414     return nullptr;
0415 }
0416 
0417 //------------------------------------------------------------------------------
0418 // Name: neg
0419 //------------------------------------------------------------------------------
0420 knumber_base *knumber_integer::neg()
0421 {
0422     mpz_neg(mpz_, mpz_);
0423     return this;
0424 }
0425 
0426 //------------------------------------------------------------------------------
0427 // Name: cmp
0428 //------------------------------------------------------------------------------
0429 knumber_base *knumber_integer::cmp()
0430 {
0431 #if 0
0432     // unfortunately this breaks things pretty badly
0433     // for non-decimal modes :-(
0434     mpz_com(mpz_, mpz_);
0435 #else
0436     mpz_swap(mpz_, knumber_integer(~toUint64()).mpz_);
0437 #endif
0438     return this;
0439 }
0440 
0441 //------------------------------------------------------------------------------
0442 // Name: abs
0443 //------------------------------------------------------------------------------
0444 knumber_base *knumber_integer::abs()
0445 {
0446     mpz_abs(mpz_, mpz_);
0447     return this;
0448 }
0449 
0450 //------------------------------------------------------------------------------
0451 // Name: sqrt
0452 //------------------------------------------------------------------------------
0453 knumber_base *knumber_integer::sqrt()
0454 {
0455     if (sign() < 0) {
0456         delete this;
0457         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0458     }
0459 
0460     if (mpz_perfect_square_p(mpz_)) {
0461         mpz_sqrt(mpz_, mpz_);
0462         return this;
0463     } else {
0464         auto f = new knumber_float(this);
0465         delete this;
0466         return f->sqrt();
0467     }
0468 }
0469 
0470 //------------------------------------------------------------------------------
0471 // Name: cbrt
0472 //------------------------------------------------------------------------------
0473 knumber_base *knumber_integer::cbrt()
0474 {
0475     mpz_t x;
0476     mpz_init_set(x, mpz_);
0477     if (mpz_root(x, x, 3)) {
0478         mpz_swap(mpz_, x);
0479         mpz_clear(x);
0480         return this;
0481     }
0482 
0483     mpz_clear(x);
0484     auto f = new knumber_float(this);
0485     delete this;
0486     return f->cbrt();
0487 }
0488 
0489 //------------------------------------------------------------------------------
0490 // Name: pow
0491 //------------------------------------------------------------------------------
0492 knumber_base *knumber_integer::pow(knumber_base *rhs)
0493 {
0494     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0495         if (is_zero() && p->is_even() && p->sign() < 0) {
0496             delete this;
0497             return new knumber_error(knumber_error::ERROR_POS_INFINITY);
0498         }
0499 
0500         mpz_pow_ui(mpz_, mpz_, mpz_get_ui(p->mpz_));
0501 
0502         if (p->sign() < 0) {
0503             return reciprocal();
0504         } else {
0505             return this;
0506         }
0507     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0508         auto f = new knumber_float(this);
0509         delete this;
0510         return f->pow(p);
0511     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0512         auto f = new knumber_fraction(this);
0513         delete this;
0514         return f->pow(p);
0515     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0516         if (p->sign() > 0) {
0517             auto e = new knumber_error(knumber_error::ERROR_POS_INFINITY);
0518             delete this;
0519             return e;
0520         } else if (p->sign() < 0) {
0521             mpz_init_set_si(mpz_, 0);
0522             return this;
0523         } else {
0524             auto e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0525             delete this;
0526             return e;
0527         }
0528     }
0529 
0530     Q_ASSERT(0);
0531     return nullptr;
0532 }
0533 
0534 //------------------------------------------------------------------------------
0535 // Name: sin
0536 //------------------------------------------------------------------------------
0537 knumber_base *knumber_integer::sin()
0538 {
0539     auto f = new knumber_float(this);
0540     delete this;
0541     return f->sin();
0542 }
0543 
0544 //------------------------------------------------------------------------------
0545 // Name: cos
0546 //------------------------------------------------------------------------------
0547 knumber_base *knumber_integer::cos()
0548 {
0549     auto f = new knumber_float(this);
0550     delete this;
0551     return f->cos();
0552 }
0553 
0554 //------------------------------------------------------------------------------
0555 // Name: tan
0556 //------------------------------------------------------------------------------
0557 knumber_base *knumber_integer::tan()
0558 {
0559     auto f = new knumber_float(this);
0560     delete this;
0561     return f->tan();
0562 }
0563 
0564 //------------------------------------------------------------------------------
0565 // Name: asin
0566 //------------------------------------------------------------------------------
0567 knumber_base *knumber_integer::asin()
0568 {
0569     auto f = new knumber_float(this);
0570     delete this;
0571     return f->asin();
0572 }
0573 
0574 //------------------------------------------------------------------------------
0575 // Name: acos
0576 //------------------------------------------------------------------------------
0577 knumber_base *knumber_integer::acos()
0578 {
0579     auto f = new knumber_float(this);
0580     delete this;
0581     return f->acos();
0582 }
0583 
0584 //------------------------------------------------------------------------------
0585 // Name: atan
0586 //------------------------------------------------------------------------------
0587 knumber_base *knumber_integer::atan()
0588 {
0589     auto f = new knumber_float(this);
0590     delete this;
0591     return f->atan();
0592 }
0593 
0594 //------------------------------------------------------------------------------
0595 // Name: tgamma
0596 //------------------------------------------------------------------------------
0597 knumber_base *knumber_integer::tgamma()
0598 {
0599     auto f = new knumber_float(this);
0600     delete this;
0601     return f->tgamma();
0602 }
0603 
0604 //------------------------------------------------------------------------------
0605 // Name:
0606 //------------------------------------------------------------------------------
0607 knumber_base *knumber_integer::sinh()
0608 {
0609     auto f = new knumber_float(this);
0610     delete this;
0611     return f->sinh();
0612 }
0613 
0614 //------------------------------------------------------------------------------
0615 // Name:
0616 //------------------------------------------------------------------------------
0617 knumber_base *knumber_integer::cosh()
0618 {
0619     auto f = new knumber_float(this);
0620     delete this;
0621     return f->cosh();
0622 }
0623 
0624 //------------------------------------------------------------------------------
0625 // Name:
0626 //------------------------------------------------------------------------------
0627 knumber_base *knumber_integer::tanh()
0628 {
0629     auto f = new knumber_float(this);
0630     delete this;
0631     return f->tanh();
0632 }
0633 
0634 //------------------------------------------------------------------------------
0635 // Name:
0636 //------------------------------------------------------------------------------
0637 knumber_base *knumber_integer::asinh()
0638 {
0639     auto f = new knumber_float(this);
0640     delete this;
0641     return f->asinh();
0642 }
0643 
0644 //------------------------------------------------------------------------------
0645 // Name:
0646 //------------------------------------------------------------------------------
0647 knumber_base *knumber_integer::acosh()
0648 {
0649     auto f = new knumber_float(this);
0650     delete this;
0651     return f->acosh();
0652 }
0653 
0654 //------------------------------------------------------------------------------
0655 // Name:
0656 //------------------------------------------------------------------------------
0657 knumber_base *knumber_integer::atanh()
0658 {
0659     auto f = new knumber_float(this);
0660     delete this;
0661     return f->atanh();
0662 }
0663 
0664 //------------------------------------------------------------------------------
0665 // Name: factorial
0666 //------------------------------------------------------------------------------
0667 knumber_base *knumber_integer::factorial()
0668 {
0669     if (sign() < 0) {
0670         delete this;
0671         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0672     }
0673 
0674     mpz_fac_ui(mpz_, mpz_get_ui(mpz_));
0675     return this;
0676 }
0677 
0678 //------------------------------------------------------------------------------
0679 // Name: compare
0680 //------------------------------------------------------------------------------
0681 int knumber_integer::compare(knumber_base *rhs)
0682 {
0683     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0684         return mpz_cmp(mpz_, p->mpz_);
0685     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0686         return knumber_float(this).compare(p);
0687     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0688         return knumber_fraction(this).compare(p);
0689     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0690         // NOTE: any number compared to NaN/Inf/-Inf always compares less
0691         //       at the moment
0692         return -1;
0693     }
0694 
0695     Q_ASSERT(0);
0696     return 0;
0697 }
0698 
0699 //------------------------------------------------------------------------------
0700 // Name: toString
0701 //------------------------------------------------------------------------------
0702 QString knumber_integer::toString(int precision) const
0703 {
0704     Q_UNUSED(precision);
0705 
0706     const size_t size = gmp_snprintf(nullptr, 0, "%Zd", mpz_) + 1;
0707     QScopedArrayPointer<char> buf(new char[size]);
0708     gmp_snprintf(&buf[0], size, "%Zd", mpz_);
0709     return QLatin1String(&buf[0]);
0710 }
0711 
0712 //------------------------------------------------------------------------------
0713 // Name:
0714 //------------------------------------------------------------------------------
0715 quint64 knumber_integer::toUint64() const
0716 {
0717     // libgmp doesn't have unsigned long long conversion
0718     // so convert to string and then to unsigned long long
0719     const QString tmpstring = toString(-1);
0720 
0721     bool ok;
0722     quint64 value;
0723 
0724     if (sign() < 0) {
0725         const qint64 signedvalue = tmpstring.toLongLong(&ok, 10);
0726         value = static_cast<quint64>(signedvalue);
0727     } else {
0728         value = tmpstring.toULongLong(&ok, 10);
0729     }
0730 
0731     if (!ok) {
0732         // TODO: what to do if error?
0733         value = 0;
0734     }
0735     return value;
0736 }
0737 
0738 //------------------------------------------------------------------------------
0739 // Name:
0740 //------------------------------------------------------------------------------
0741 qint64 knumber_integer::toInt64() const
0742 {
0743     // libgmp doesn't have long long conversion
0744     // so convert to string and then to long long
0745     const QString tmpstring = toString(-1);
0746 
0747     bool ok;
0748     qint64 value = tmpstring.toLongLong(&ok, 10);
0749 
0750     if (!ok) {
0751         // TODO: what to do if error?
0752         value = 0;
0753     }
0754 
0755     return value;
0756 }
0757 
0758 //------------------------------------------------------------------------------
0759 // Name: is_integer
0760 //------------------------------------------------------------------------------
0761 bool knumber_integer::is_integer() const
0762 {
0763     return true;
0764 }
0765 
0766 //------------------------------------------------------------------------------
0767 // Name: is_zero
0768 //------------------------------------------------------------------------------
0769 bool knumber_integer::is_zero() const
0770 {
0771     return mpz_sgn(mpz_) == 0;
0772 }
0773 
0774 //------------------------------------------------------------------------------
0775 // Name: sign
0776 //------------------------------------------------------------------------------
0777 int knumber_integer::sign() const
0778 {
0779     return mpz_sgn(mpz_);
0780 }
0781 
0782 //------------------------------------------------------------------------------
0783 // Name: is_even
0784 //------------------------------------------------------------------------------
0785 bool knumber_integer::is_even() const
0786 {
0787     return mpz_even_p(mpz_);
0788 }
0789 
0790 //------------------------------------------------------------------------------
0791 // Name: is_odd
0792 //------------------------------------------------------------------------------
0793 bool knumber_integer::is_odd() const
0794 {
0795     return mpz_odd_p(mpz_);
0796 }
0797 
0798 //------------------------------------------------------------------------------
0799 // Name: reciprocal
0800 //------------------------------------------------------------------------------
0801 knumber_base *knumber_integer::reciprocal()
0802 {
0803     auto q = new knumber_fraction(this);
0804     delete this;
0805     return q->reciprocal();
0806 }
0807 
0808 //------------------------------------------------------------------------------
0809 // Name: log2
0810 //------------------------------------------------------------------------------
0811 knumber_base *knumber_integer::log2()
0812 {
0813     auto f = new knumber_float(this);
0814     delete this;
0815     return f->log2();
0816 }
0817 
0818 //------------------------------------------------------------------------------
0819 // Name: floor
0820 //------------------------------------------------------------------------------
0821 knumber_base *knumber_integer::floor()
0822 {
0823     // should have no effect on the value
0824     return this;
0825 }
0826 
0827 //------------------------------------------------------------------------------
0828 // Name: ceil
0829 //------------------------------------------------------------------------------
0830 knumber_base *knumber_integer::ceil()
0831 {
0832     // should have no effect on the value
0833     return this;
0834 }
0835 
0836 //------------------------------------------------------------------------------
0837 // Name: log10
0838 //------------------------------------------------------------------------------
0839 knumber_base *knumber_integer::log10()
0840 {
0841     auto f = new knumber_float(this);
0842     delete this;
0843     return f->log10();
0844 }
0845 
0846 //------------------------------------------------------------------------------
0847 // Name: ln
0848 //------------------------------------------------------------------------------
0849 knumber_base *knumber_integer::ln()
0850 {
0851     auto f = new knumber_float(this);
0852     delete this;
0853     return f->ln();
0854 }
0855 
0856 //------------------------------------------------------------------------------
0857 // Name: exp2
0858 //------------------------------------------------------------------------------
0859 knumber_base *knumber_integer::exp2()
0860 {
0861     auto f = new knumber_float(this);
0862     delete this;
0863     return f->exp2();
0864 }
0865 
0866 //------------------------------------------------------------------------------
0867 // Name: exp10
0868 //------------------------------------------------------------------------------
0869 knumber_base *knumber_integer::exp10()
0870 {
0871     auto f = new knumber_float(this);
0872     delete this;
0873     return f->exp10();
0874 }
0875 
0876 //------------------------------------------------------------------------------
0877 // Name: exp
0878 //------------------------------------------------------------------------------
0879 knumber_base *knumber_integer::exp()
0880 {
0881     auto f = new knumber_float(this);
0882     delete this;
0883     return f->exp();
0884 }
0885 
0886 //------------------------------------------------------------------------------
0887 // Name: bin
0888 //------------------------------------------------------------------------------
0889 knumber_base *knumber_integer::bin(knumber_base *rhs)
0890 {
0891     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0892         mpz_bin_ui(mpz_, mpz_, mpz_get_ui(p->mpz_));
0893         return this;
0894 
0895     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0896         delete this;
0897         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0898     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0899         delete this;
0900         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0901     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0902         delete this;
0903         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0904     }
0905 
0906     Q_ASSERT(0);
0907     return nullptr;
0908 }
0909 
0910 }