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