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

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 
0026 namespace detail {
0027 
0028 bool knumber_fraction::default_fractional_input              = false;
0029 bool knumber_fraction::default_fractional_output             = true;
0030 bool knumber_fraction::split_off_integer_for_fraction_output = false;
0031 
0032 //------------------------------------------------------------------------------
0033 // Name:
0034 //------------------------------------------------------------------------------
0035 void knumber_fraction::set_default_fractional_input(bool value) {
0036     default_fractional_input = value;
0037 }
0038 
0039 //------------------------------------------------------------------------------
0040 // Name:
0041 //------------------------------------------------------------------------------
0042 void knumber_fraction::set_default_fractional_output(bool value) {
0043     default_fractional_output = value;
0044 }
0045 
0046 //------------------------------------------------------------------------------
0047 // Name:
0048 //------------------------------------------------------------------------------
0049 void knumber_fraction::set_split_off_integer_for_fraction_output(bool value) {
0050     split_off_integer_for_fraction_output = value;
0051 }
0052 
0053 //------------------------------------------------------------------------------
0054 // Name:
0055 //------------------------------------------------------------------------------
0056 knumber_fraction::knumber_fraction(const QString &s) {
0057     mpq_init(mpq_);
0058         mpq_set_str(mpq_, s.toLatin1().constData(), 10);
0059     mpq_canonicalize(mpq_);
0060 }
0061 
0062 //------------------------------------------------------------------------------
0063 // Name:
0064 //------------------------------------------------------------------------------
0065 knumber_fraction::knumber_fraction(qint64 num, quint64 den) {
0066     mpq_init(mpq_);
0067     mpq_set_si(mpq_, num, den);
0068     mpq_canonicalize(mpq_);
0069 }
0070 
0071 //------------------------------------------------------------------------------
0072 // Name:
0073 //------------------------------------------------------------------------------
0074 knumber_fraction::knumber_fraction(quint64 num, quint64 den) {
0075     mpq_init(mpq_);
0076     mpq_set_ui(mpq_, num, den);
0077     mpq_canonicalize(mpq_);
0078 }
0079 
0080 //------------------------------------------------------------------------------
0081 // Name:
0082 //------------------------------------------------------------------------------
0083 knumber_fraction::knumber_fraction(mpq_t mpq) {
0084     mpq_init(mpq_);
0085     mpq_set(mpq_, mpq);
0086 }
0087 
0088 //------------------------------------------------------------------------------
0089 // Name:
0090 //------------------------------------------------------------------------------
0091 knumber_fraction::knumber_fraction(const knumber_fraction *value) {
0092     mpq_init(mpq_);
0093     mpq_set(mpq_, value->mpq_);
0094 }
0095 
0096 //------------------------------------------------------------------------------
0097 // Name:
0098 //------------------------------------------------------------------------------
0099 knumber_fraction::knumber_fraction(const knumber_integer *value) {
0100     mpq_init(mpq_);
0101     mpq_set_z(mpq_, value->mpz_);
0102 }
0103 
0104 #if 0
0105 //------------------------------------------------------------------------------
0106 // Name:
0107 //------------------------------------------------------------------------------
0108 knumber_fraction::knumber_fraction(const knumber_float *value) {
0109     mpq_init(mpq_);
0110     mpq_set_f(mpq_, value->mpf_);
0111 }
0112 #endif
0113 
0114 //------------------------------------------------------------------------------
0115 // Name:
0116 //------------------------------------------------------------------------------
0117 knumber_base *knumber_fraction::clone() {
0118     return new knumber_fraction(this);
0119 }
0120 
0121 //------------------------------------------------------------------------------
0122 // Name:
0123 //------------------------------------------------------------------------------
0124 knumber_fraction::~knumber_fraction() {
0125     mpq_clear(mpq_);
0126 }
0127 
0128 //------------------------------------------------------------------------------
0129 // Name:
0130 //------------------------------------------------------------------------------
0131 bool knumber_fraction::is_integer() const {
0132     return (mpz_cmp_ui(mpq_denref(mpq_), 1) == 0);
0133 }
0134 
0135 //------------------------------------------------------------------------------
0136 // Name:
0137 //------------------------------------------------------------------------------
0138 knumber_base *knumber_fraction::add(knumber_base *rhs) {
0139 
0140     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0141         knumber_fraction q(p);
0142         mpq_add(mpq_, mpq_, q.mpq_);
0143         return this;
0144     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0145         knumber_float *f = new knumber_float(this);
0146         delete this;
0147         return f->add(p);
0148     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0149         mpq_add(mpq_, mpq_, p->mpq_);
0150         return this;
0151     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0152         knumber_error *e = new knumber_error(p);
0153         delete this;
0154         return e;
0155     }
0156 
0157     Q_ASSERT(0);
0158     return nullptr;
0159 }
0160 
0161 //------------------------------------------------------------------------------
0162 // Name:
0163 //------------------------------------------------------------------------------
0164 knumber_base *knumber_fraction::sub(knumber_base *rhs) {
0165 
0166     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0167         knumber_fraction q(p);
0168         mpq_sub(mpq_, mpq_, q.mpq_);
0169         return this;
0170     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0171         knumber_float *f = new knumber_float(this);
0172         delete this;
0173         return f->sub(p);
0174     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0175         mpq_sub(mpq_, mpq_, p->mpq_);
0176         return this;
0177     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0178         knumber_error *e = new knumber_error(p);
0179         delete this;
0180         return e->neg();
0181     }
0182 
0183     Q_ASSERT(0);
0184     return nullptr;
0185 }
0186 
0187 //------------------------------------------------------------------------------
0188 // Name:
0189 //------------------------------------------------------------------------------
0190 knumber_base *knumber_fraction::mul(knumber_base *rhs) {
0191 
0192     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0193         knumber_fraction q(p);
0194         mpq_mul(mpq_, mpq_, q.mpq_);
0195         return this;
0196     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0197         knumber_float *q = new knumber_float(this);
0198         delete this;
0199         return q->mul(p);
0200     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0201         mpq_mul(mpq_, mpq_, p->mpq_);
0202         return this;
0203     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0204         if(is_zero()) {
0205             delete this;
0206             knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0207             return e;
0208         }
0209 
0210         if(sign() < 0) {
0211             delete this;
0212             knumber_error *e = new knumber_error(p);
0213             return e->neg();
0214         } else {
0215             delete this;
0216             knumber_error *e = new knumber_error(p);
0217             return e;
0218         }
0219     }
0220 
0221     Q_ASSERT(0);
0222     return nullptr;
0223 }
0224 
0225 //------------------------------------------------------------------------------
0226 // Name:
0227 //------------------------------------------------------------------------------
0228 knumber_base *knumber_fraction::div(knumber_base *rhs) {
0229 
0230     if(rhs->is_zero()) {
0231         if(sign() < 0) {
0232             delete this;
0233             return new knumber_error(knumber_error::ERROR_NEG_INFINITY);
0234         } else {
0235             delete this;
0236             return new knumber_error(knumber_error::ERROR_POS_INFINITY);
0237         }
0238     }
0239 
0240     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0241         knumber_fraction f(p);
0242         return div(&f);
0243     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0244         knumber_float *f = new knumber_float(this);
0245         delete this;
0246         return f->div(p);
0247     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0248         mpq_div(mpq_, mpq_, p->mpq_);
0249         return this;
0250     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0251 
0252         if(p->sign() > 0) {
0253             delete this;
0254             return new knumber_integer(0);
0255         } else if(p->sign() < 0) {
0256             delete this;
0257             return new knumber_integer(0);
0258         }
0259 
0260         knumber_error *e = new knumber_error(p);
0261         delete this;
0262         return e;
0263     }
0264 
0265     Q_ASSERT(0);
0266     return nullptr;
0267 }
0268 
0269 //------------------------------------------------------------------------------
0270 // Name:
0271 //------------------------------------------------------------------------------
0272 knumber_base *knumber_fraction::mod(knumber_base *rhs) {
0273 
0274     if(rhs->is_zero()) {
0275         delete this;
0276         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0277     }
0278 
0279     // NOTE: we don't support modulus operations with non-integer operands
0280     mpq_set_d(mpq_, 0);
0281     return this;
0282 }
0283 
0284 //------------------------------------------------------------------------------
0285 // Name:
0286 //------------------------------------------------------------------------------
0287 knumber_base *knumber_fraction::bitwise_and(knumber_base *rhs) {
0288 
0289     Q_UNUSED(rhs);
0290     delete this;
0291     // NOTE: we don't support bitwise operations with non-integer operands
0292     return new knumber_integer(0);
0293 }
0294 
0295 //------------------------------------------------------------------------------
0296 // Name:
0297 //------------------------------------------------------------------------------
0298 knumber_base *knumber_fraction::bitwise_xor(knumber_base *rhs) {
0299 
0300     Q_UNUSED(rhs);
0301     delete this;
0302     // NOTE: we don't support bitwise operations with non-integer operands
0303     return new knumber_integer(0);
0304 }
0305 
0306 //------------------------------------------------------------------------------
0307 // Name:
0308 //------------------------------------------------------------------------------
0309 knumber_base *knumber_fraction::bitwise_or(knumber_base *rhs) {
0310 
0311     Q_UNUSED(rhs);
0312     delete this;
0313     // NOTE: we don't support bitwise operations with non-integer operands
0314     return new knumber_integer(0);
0315 }
0316 
0317 //------------------------------------------------------------------------------
0318 // Name:
0319 //------------------------------------------------------------------------------
0320 knumber_base *knumber_fraction::bitwise_shift(knumber_base *rhs) {
0321 
0322     Q_UNUSED(rhs);
0323     delete this;
0324     // NOTE: we don't support bitwise operations with non-integer operands
0325     return new knumber_error(knumber_error::ERROR_UNDEFINED);
0326 }
0327 
0328 //------------------------------------------------------------------------------
0329 // Name:
0330 //------------------------------------------------------------------------------
0331 knumber_base *knumber_fraction::neg() {
0332     mpq_neg(mpq_, mpq_);
0333     return this;
0334 }
0335 
0336 //------------------------------------------------------------------------------
0337 // Name:
0338 //------------------------------------------------------------------------------
0339 knumber_base *knumber_fraction::abs() {
0340     mpq_abs(mpq_, mpq_);
0341     return this;
0342 }
0343 
0344 //------------------------------------------------------------------------------
0345 // Name:
0346 //------------------------------------------------------------------------------
0347 knumber_base *knumber_fraction::cmp() {
0348 
0349     delete this;
0350     return new knumber_error(knumber_error::ERROR_UNDEFINED);
0351 }
0352 
0353 //------------------------------------------------------------------------------
0354 // Name:
0355 //------------------------------------------------------------------------------
0356 knumber_base *knumber_fraction::sqrt() {
0357 
0358     if(sign() < 0) {
0359         delete this;
0360         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0361     }
0362 
0363     if(mpz_perfect_square_p(mpq_numref(mpq_)) && mpz_perfect_square_p(mpq_denref(mpq_))) {
0364         mpz_t num;
0365         mpz_t den;
0366         mpz_init(num);
0367         mpz_init(den);
0368         mpq_get_num(num, mpq_);
0369         mpq_get_den(den, mpq_);
0370         mpz_sqrt(num, num);
0371         mpz_sqrt(den, den);
0372         mpq_set_num(mpq_, num);
0373         mpq_set_den(mpq_, den);
0374         mpq_canonicalize(mpq_);
0375         mpz_clear(num);
0376         mpz_clear(den);
0377         return this;
0378     } else {
0379         knumber_float *f = new knumber_float(this);
0380         delete this;
0381         return f->sqrt();
0382     }
0383 }
0384 
0385 //------------------------------------------------------------------------------
0386 // Name:
0387 //------------------------------------------------------------------------------
0388 knumber_base *knumber_fraction::cbrt() {
0389 
0390     // TODO: figure out how to properly use mpq_numref/mpq_denref here
0391     mpz_t num;
0392     mpz_t den;
0393 
0394     mpz_init(num);
0395     mpz_init(den);
0396 
0397     mpq_get_num(num, mpq_);
0398     mpq_get_den(den, mpq_);
0399 
0400     if(mpz_root(num, num, 3) && mpz_root(den, den, 3)) {
0401         mpq_set_num(mpq_, num);
0402         mpq_set_den(mpq_, den);
0403         mpq_canonicalize(mpq_);
0404         mpz_clear(num);
0405         mpz_clear(den);
0406         return this;
0407     } else {
0408         mpz_clear(num);
0409         mpz_clear(den);
0410         knumber_float *f = new knumber_float(this);
0411         delete this;
0412         return f->cbrt();
0413     }
0414 }
0415 
0416 //------------------------------------------------------------------------------
0417 // Name:
0418 //------------------------------------------------------------------------------
0419 knumber_base *knumber_fraction::factorial() {
0420 
0421     if(sign() < 0) {
0422         delete this;
0423         return new knumber_error(knumber_error::ERROR_UNDEFINED);
0424     }
0425 
0426     knumber_integer *i = new knumber_integer(this);
0427     delete this;
0428     return i->factorial();
0429 }
0430 
0431 //------------------------------------------------------------------------------
0432 // Name:
0433 //------------------------------------------------------------------------------
0434 knumber_base *knumber_fraction::pow(knumber_base *rhs) {
0435 
0436     // TODO: figure out how to properly use mpq_numref/mpq_denref here
0437     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0438 
0439         mpz_t num;
0440         mpz_t den;
0441 
0442         mpz_init(num);
0443         mpz_init(den);
0444 
0445         mpq_get_num(num, mpq_);
0446         mpq_get_den(den, mpq_);
0447 
0448         mpz_pow_ui(num, num, mpz_get_ui(p->mpz_));
0449         mpz_pow_ui(den, den, mpz_get_ui(p->mpz_));
0450         mpq_set_num(mpq_, num);
0451         mpq_set_den(mpq_, den);
0452         mpq_canonicalize(mpq_);
0453         mpz_clear(num);
0454         mpz_clear(den);
0455 
0456         if(p->sign() < 0) {
0457             return reciprocal();
0458         } else {
0459             return this;
0460         }
0461     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0462         Q_UNUSED(p);
0463         knumber_float *f = new knumber_float(this);
0464         delete this;
0465         return f->pow(rhs);
0466     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0467 
0468         // ok, so if any part of the number is > 1,000,000, then we risk
0469         // the pow function overflowing... so we'll just convert to float to be safe
0470         // TODO: at some point, we should figure out exactly what the threshold is
0471         //       and if there is a better way to determine if the pow function will
0472         //       overflow.
0473         if(mpz_cmpabs_ui(mpq_numref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_numref(p->mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(p->mpq_), 1000000) > 0) {
0474             knumber_float *f = new knumber_float(this);
0475             delete this;
0476             return f->pow(rhs);
0477         }
0478 
0479         mpz_t lhs_num;
0480         mpz_t lhs_den;
0481         mpz_t rhs_num;
0482         mpz_t rhs_den;
0483 
0484         mpz_init(lhs_num);
0485         mpz_init(lhs_den);
0486         mpz_init(rhs_num);
0487         mpz_init(rhs_den);
0488 
0489         mpq_get_num(lhs_num, mpq_);
0490         mpq_get_den(lhs_den, mpq_);
0491         mpq_get_num(rhs_num, p->mpq_);
0492         mpq_get_den(rhs_den, p->mpq_);
0493 
0494         mpz_pow_ui(lhs_num, lhs_num, mpz_get_ui(rhs_num));
0495         mpz_pow_ui(lhs_den, lhs_den, mpz_get_ui(rhs_num));
0496 
0497         if(mpz_sgn(lhs_num) < 0 && mpz_even_p(rhs_den)) {
0498             mpz_clear(lhs_num);
0499             mpz_clear(lhs_den);
0500             mpz_clear(rhs_num);
0501             mpz_clear(rhs_den);
0502             delete this;
0503             return new knumber_error(knumber_error::ERROR_UNDEFINED);
0504         }
0505 
0506         if(mpz_sgn(lhs_den) < 0 && mpz_even_p(rhs_den)) {
0507             mpz_clear(lhs_num);
0508             mpz_clear(lhs_den);
0509             mpz_clear(rhs_num);
0510             mpz_clear(rhs_den);
0511             delete this;
0512             return new knumber_error(knumber_error::ERROR_UNDEFINED);
0513         }
0514 
0515         const int n1 = mpz_root(lhs_num, lhs_num, mpz_get_ui(rhs_den));
0516         const int n2 = mpz_root(lhs_den, lhs_den, mpz_get_ui(rhs_den));
0517 
0518         if(n1 && n2) {
0519 
0520             mpq_set_num(mpq_, lhs_num);
0521             mpq_set_den(mpq_, lhs_den);
0522             mpq_canonicalize(mpq_);
0523             mpz_clear(lhs_num);
0524             mpz_clear(lhs_den);
0525             mpz_clear(rhs_num);
0526             mpz_clear(rhs_den);
0527 
0528             if(p->sign() < 0) {
0529                 return reciprocal();
0530             } else {
0531                 return this;
0532             }
0533         } else {
0534             mpz_clear(lhs_num);
0535             mpz_clear(lhs_den);
0536             mpz_clear(rhs_num);
0537             mpz_clear(rhs_den);
0538             knumber_float *f = new knumber_float(this);
0539             delete this;
0540 
0541             return f->pow(rhs);
0542         }
0543 
0544     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0545         if(p->sign() > 0) {
0546             knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY);
0547             delete this;
0548             return e;
0549         } else if(p->sign() < 0) {
0550             knumber_integer *n = new knumber_integer(0);
0551             delete this;
0552             return n;
0553         } else {
0554             knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED);
0555             delete this;
0556             return e;
0557         }
0558     }
0559 
0560     Q_ASSERT(0);
0561     return nullptr;
0562 }
0563 
0564 //------------------------------------------------------------------------------
0565 // Name:
0566 //------------------------------------------------------------------------------
0567 knumber_base *knumber_fraction::sin() {
0568 
0569     knumber_float *f = new knumber_float(this);
0570     delete this;
0571     return f->sin();
0572 }
0573 
0574 //------------------------------------------------------------------------------
0575 // Name:
0576 //------------------------------------------------------------------------------
0577 knumber_base *knumber_fraction::floor() {
0578     knumber_float *f = new knumber_float(this);
0579     delete this;
0580     return f->floor();
0581 }
0582 
0583 //------------------------------------------------------------------------------
0584 // Name:
0585 //------------------------------------------------------------------------------
0586 knumber_base *knumber_fraction::ceil() {
0587     knumber_float *f = new knumber_float(this);
0588     delete this;
0589     return f->ceil();
0590 }
0591 
0592 //------------------------------------------------------------------------------
0593 // Name:
0594 //------------------------------------------------------------------------------
0595 knumber_base *knumber_fraction::cos() {
0596 
0597     knumber_float *f = new knumber_float(this);
0598     delete this;
0599     return f->cos();
0600 }
0601 
0602 //------------------------------------------------------------------------------
0603 // Name:
0604 //------------------------------------------------------------------------------
0605 knumber_base *knumber_fraction::tgamma() {
0606 
0607     knumber_float *f = new knumber_float(this);
0608     delete this;
0609     return f->tgamma();
0610 }
0611 
0612 //------------------------------------------------------------------------------
0613 // Name:
0614 //------------------------------------------------------------------------------
0615 knumber_base *knumber_fraction::tan() {
0616 
0617     knumber_float *f = new knumber_float(this);
0618     delete this;
0619     return f->tan();
0620 }
0621 
0622 //------------------------------------------------------------------------------
0623 // Name:
0624 //------------------------------------------------------------------------------
0625 knumber_base *knumber_fraction::asin() {
0626 
0627     knumber_float *f = new knumber_float(this);
0628     delete this;
0629     return f->asin();
0630 }
0631 
0632 //------------------------------------------------------------------------------
0633 // Name:
0634 //------------------------------------------------------------------------------
0635 knumber_base *knumber_fraction::acos() {
0636 
0637     knumber_float *f = new knumber_float(this);
0638     delete this;
0639     return f->acos();
0640 }
0641 
0642 //------------------------------------------------------------------------------
0643 // Name:
0644 //------------------------------------------------------------------------------
0645 knumber_base *knumber_fraction::atan() {
0646 
0647     knumber_float *f = new knumber_float(this);
0648     delete this;
0649     return f->atan();
0650 }
0651 
0652 //------------------------------------------------------------------------------
0653 // Name:
0654 //------------------------------------------------------------------------------
0655 knumber_base *knumber_fraction::sinh() {
0656     knumber_float *f = new knumber_float(this);
0657     delete this;
0658     return f->sinh();
0659 }
0660 
0661 //------------------------------------------------------------------------------
0662 // Name:
0663 //------------------------------------------------------------------------------
0664 knumber_base *knumber_fraction::cosh() {
0665     knumber_float *f = new knumber_float(this);
0666     delete this;
0667     return f->cosh();
0668 }
0669 
0670 //------------------------------------------------------------------------------
0671 // Name:
0672 //------------------------------------------------------------------------------
0673 knumber_base *knumber_fraction::tanh() {
0674     knumber_float *f = new knumber_float(this);
0675     delete this;
0676     return f->tanh();
0677 }
0678 
0679 //------------------------------------------------------------------------------
0680 // Name:
0681 //------------------------------------------------------------------------------
0682 knumber_base *knumber_fraction::asinh() {
0683     knumber_float *f = new knumber_float(this);
0684     delete this;
0685     return f->asinh();
0686 }
0687 
0688 //------------------------------------------------------------------------------
0689 // Name:
0690 //------------------------------------------------------------------------------
0691 knumber_base *knumber_fraction::acosh() {
0692     knumber_float *f = new knumber_float(this);
0693     delete this;
0694     return f->acosh();
0695 }
0696 
0697 //------------------------------------------------------------------------------
0698 // Name:
0699 //------------------------------------------------------------------------------
0700 knumber_base *knumber_fraction::atanh() {
0701     knumber_float *f = new knumber_float(this);
0702     delete this;
0703     return f->atanh();
0704 }
0705 
0706 //------------------------------------------------------------------------------
0707 // Name:
0708 //------------------------------------------------------------------------------
0709 int knumber_fraction::compare(knumber_base *rhs) {
0710 
0711     if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) {
0712         knumber_fraction f(p);
0713         return mpq_cmp(mpq_, f.mpq_);
0714     } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) {
0715         knumber_float f(this);
0716         return f.compare(p);
0717     } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) {
0718         return mpq_cmp(mpq_, p->mpq_);
0719     } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) {
0720         // NOTE: any number compared to NaN/Inf/-Inf always compares less
0721         //       at the moment
0722         return -1;
0723     }
0724 
0725     Q_ASSERT(0);
0726     return 0;
0727 }
0728 
0729 //------------------------------------------------------------------------------
0730 // Name:
0731 //------------------------------------------------------------------------------
0732 QString knumber_fraction::toString(int precision) const {
0733 
0734 
0735     if(knumber_fraction::default_fractional_output) {
0736 
0737         // TODO: figure out how to properly use mpq_numref/mpq_denref here
0738 
0739         knumber_integer integer_part(this);
0740         if(split_off_integer_for_fraction_output && !integer_part.is_zero()) {
0741 
0742             mpz_t num;
0743             mpz_init(num);
0744             mpq_get_num(num, mpq_);
0745 
0746             knumber_integer integer_part_1(this);
0747 
0748             mpz_mul(integer_part.mpz_, integer_part.mpz_, mpq_denref(mpq_));
0749             mpz_sub(num, num, integer_part.mpz_);
0750 
0751             if(mpz_sgn(num) < 0) {
0752                 mpz_neg(num, num);
0753             }
0754 
0755             const size_t size = gmp_snprintf(nullptr, 0, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1;
0756             QScopedArrayPointer<char> buf(new char[size]);
0757             gmp_snprintf(&buf[0], size, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_));
0758 
0759             mpz_clear(num);
0760 
0761             return QLatin1String(&buf[0]);
0762         } else {
0763 
0764             mpz_t num;
0765             mpz_init(num);
0766             mpq_get_num(num, mpq_);
0767 
0768             const size_t size = gmp_snprintf(nullptr, 0, "%Zd/%Zd", num, mpq_denref(mpq_)) + 1;
0769             QScopedArrayPointer<char> buf(new char[size]);
0770             gmp_snprintf(&buf[0], size, "%Zd/%Zd", num, mpq_denref(mpq_));
0771 
0772             mpz_clear(num);
0773 
0774             return QLatin1String(&buf[0]);
0775         }
0776     } else {
0777         return knumber_float(this).toString(precision);
0778     }
0779 }
0780 QString knumber_fraction::toBinaryString(int precision) const {
0781 
0782 
0783     if(knumber_fraction::default_fractional_output) {
0784 
0785         // TODO: figure out how to properly use mpq_numref/mpq_denref here
0786 
0787         knumber_integer integer_part(this);
0788         if(split_off_integer_for_fraction_output && !integer_part.is_zero()) {
0789 
0790             mpz_t num;
0791             mpz_init(num);
0792             mpq_get_num(num, mpq_);
0793 
0794             knumber_integer integer_part_1(this);
0795 
0796             mpz_mul(integer_part.mpz_, integer_part.mpz_, mpq_denref(mpq_));
0797             mpz_sub(num, num, integer_part.mpz_);
0798 
0799             if(mpz_sgn(num) < 0) {
0800                 mpz_neg(num, num);
0801             }
0802 
0803             const size_t size = gmp_snprintf(nullptr, 0, "%Zb %Zb/%Zb", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1;
0804             QScopedArrayPointer<char> buf(new char[size]);
0805             gmp_snprintf(&buf[0], size, "%Zb %Zb/%Zb", integer_part_1.mpz_, num, mpq_denref(mpq_));
0806 
0807             mpz_clear(num);
0808 
0809             return QLatin1String(&buf[0]);
0810         } else {
0811 
0812             mpz_t num;
0813             mpz_init(num);
0814             mpq_get_num(num, mpq_);
0815 
0816             const size_t size = gmp_snprintf(nullptr, 0, "%Zb/%Zb", num, mpq_denref(mpq_)) + 1;
0817             QScopedArrayPointer<char> buf(new char[size]);
0818             gmp_snprintf(&buf[0], size, "%Zb/%Zb", num, mpq_denref(mpq_));
0819 
0820             mpz_clear(num);
0821 
0822             return QLatin1String(&buf[0]);
0823         }
0824     } else {
0825         return knumber_float(this).toString(precision);
0826     }
0827 }
0828 QString knumber_fraction::toHexString(int precision) const {
0829     if(knumber_fraction::default_fractional_output) {
0830 
0831         // TODO: figure out how to properly use mpq_numref/mpq_denref here
0832 
0833         knumber_integer integer_part(this);
0834         if(split_off_integer_for_fraction_output && !integer_part.is_zero()) {
0835 
0836             mpz_t num;
0837             mpz_init(num);
0838             mpq_get_num(num, mpq_);
0839 
0840             knumber_integer integer_part_1(this);
0841 
0842             mpz_mul(integer_part.mpz_, integer_part.mpz_, mpq_denref(mpq_));
0843             mpz_sub(num, num, integer_part.mpz_);
0844 
0845             if(mpz_sgn(num) < 0) {
0846                 mpz_neg(num, num);
0847             }
0848 
0849             const size_t size = gmp_snprintf(nullptr, 0, "%Zh %Zh/%Zh", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1;
0850             QScopedArrayPointer<char> buf(new char[size]);
0851             gmp_snprintf(&buf[0], size, "%Zh %Zh/%Zh", integer_part_1.mpz_, num, mpq_denref(mpq_));
0852 
0853             mpz_clear(num);
0854 
0855             return QLatin1String(&buf[0]);
0856         } else {
0857 
0858             mpz_t num;
0859             mpz_init(num);
0860             mpq_get_num(num, mpq_);
0861 
0862             const size_t size = gmp_snprintf(nullptr, 0, "%Zh/%Zh", num, mpq_denref(mpq_)) + 1;
0863             QScopedArrayPointer<char> buf(new char[size]);
0864             gmp_snprintf(&buf[0], size, "%Zh/%Zh", num, mpq_denref(mpq_));
0865 
0866             mpz_clear(num);
0867 
0868             return QLatin1String(&buf[0]);
0869         }
0870     } else {
0871         return knumber_float(this).toString(precision);
0872     }
0873 }
0874 //------------------------------------------------------------------------------
0875 // Name:
0876 //------------------------------------------------------------------------------
0877 bool knumber_fraction::is_zero() const {
0878     return mpq_sgn(mpq_) == 0;
0879 }
0880 
0881 //------------------------------------------------------------------------------
0882 // Name:
0883 //------------------------------------------------------------------------------
0884 int knumber_fraction::sign() const {
0885     return mpq_sgn(mpq_);
0886 }
0887 
0888 //------------------------------------------------------------------------------
0889 // Name:
0890 //------------------------------------------------------------------------------
0891 knumber_base *knumber_fraction::reciprocal() {
0892 
0893     mpq_inv(mpq_, mpq_);
0894     return this;
0895 }
0896 
0897 //------------------------------------------------------------------------------
0898 // Name:
0899 //------------------------------------------------------------------------------
0900 knumber_integer *knumber_fraction::numerator() const {
0901 
0902     mpz_t num;
0903     mpz_init(num);
0904     mpq_get_num(num, mpq_);
0905     knumber_integer *n = new knumber_integer(num);
0906     mpz_clear(num);
0907     return n;
0908 }
0909 
0910 //------------------------------------------------------------------------------
0911 // Name:
0912 //------------------------------------------------------------------------------
0913 knumber_integer *knumber_fraction::denominator() const {
0914 
0915     mpz_t den;
0916     mpz_init(den);
0917     mpq_get_den(den, mpq_);
0918     knumber_integer *n = new knumber_integer(den);
0919     mpz_clear(den);
0920     return n;
0921 }
0922 
0923 //------------------------------------------------------------------------------
0924 // Name:
0925 //------------------------------------------------------------------------------
0926 knumber_base *knumber_fraction::log2() {
0927     knumber_float *f = new knumber_float(this);
0928     delete this;
0929     return f->log2();
0930 }
0931 
0932 //------------------------------------------------------------------------------
0933 // Name:
0934 //------------------------------------------------------------------------------
0935 knumber_base *knumber_fraction::log10() {
0936     knumber_float *f = new knumber_float(this);
0937     delete this;
0938     return f->log10();
0939 }
0940 
0941 //------------------------------------------------------------------------------
0942 // Name:
0943 //------------------------------------------------------------------------------
0944 knumber_base *knumber_fraction::ln() {
0945     knumber_float *f = new knumber_float(this);
0946     delete this;
0947     return f->ln();
0948 }
0949 
0950 //------------------------------------------------------------------------------
0951 // Name:
0952 //------------------------------------------------------------------------------
0953 knumber_base *knumber_fraction::exp2() {
0954     knumber_float *f = new knumber_float(this);
0955     delete this;
0956     return f->exp2();
0957 }
0958 
0959 //------------------------------------------------------------------------------
0960 // Name:
0961 //------------------------------------------------------------------------------
0962 knumber_base *knumber_fraction::exp10() {
0963     knumber_float *f = new knumber_float(this);
0964     delete this;
0965     return f->exp10();
0966 }
0967 
0968 //------------------------------------------------------------------------------
0969 // Name:
0970 //------------------------------------------------------------------------------
0971 knumber_base *knumber_fraction::exp() {
0972     knumber_float *f = new knumber_float(this);
0973     delete this;
0974     return f->exp();
0975 }
0976 
0977 //------------------------------------------------------------------------------
0978 // Name:
0979 //------------------------------------------------------------------------------
0980 quint64 knumber_fraction::toUint64() const {
0981     return knumber_integer(this).toUint64();
0982 }
0983 
0984 //------------------------------------------------------------------------------
0985 // Name:
0986 //------------------------------------------------------------------------------
0987 qint64 knumber_fraction::toInt64() const {
0988     return knumber_integer(this).toInt64();
0989 }
0990 
0991 //------------------------------------------------------------------------------
0992 // Name:
0993 //------------------------------------------------------------------------------
0994 knumber_base *knumber_fraction::bin(knumber_base *rhs) {
0995     Q_UNUSED(rhs);
0996     delete this;
0997     return new knumber_error(knumber_error::ERROR_UNDEFINED);
0998 
0999 }
1000 
1001 }