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 }