File indexing completed on 2024-05-12 17:21:06

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