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