File indexing completed on 2024-05-12 04:45:54

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