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