knumber_priv.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include <math.h> 00021 #include <config.h> 00022 00023 #ifdef HAVE_STDLIB_H 00024 #include <stdlib.h> 00025 #endif 00026 #include <tqregexp.h> 00027 #include <tqstring.h> 00028 00029 #include "knumber_priv.h" 00030 00031 _knumerror::_knumerror(_knumber const & num) 00032 { 00033 switch(num.type()) { 00034 case SpecialType: 00035 _error = dynamic_cast<_knumerror const &>(num)._error; 00036 break; 00037 case IntegerType: 00038 case FractionType: 00039 case FloatType: 00040 // What should I do here? 00041 break; 00042 } 00043 } 00044 00045 00046 00047 _knuminteger::_knuminteger(unsigned long long int num) 00048 { 00049 mpz_init(_mpz); 00050 #if SIZEOF_UNSIGNED_LONG == 8 00051 mpz_init_set_ui(_mpz, static_cast<unsigned long int>(num)); 00052 #elif SIZEOF_UNSIGNED_LONG == 4 00053 mpz_set_ui(_mpz, static_cast<unsigned long int>(num >> 32)); 00054 mpz_mul_2exp(_mpz, _mpz, 32); 00055 mpz_add_ui(_mpz, _mpz, static_cast<unsigned long int>(num)); 00056 #else 00057 #error "SIZEOF_UNSIGNED_LONG is a unhandled case" 00058 #endif 00059 } 00060 00061 00062 _knuminteger::_knuminteger(_knumber const & num) 00063 { 00064 mpz_init(_mpz); 00065 00066 switch(num.type()) { 00067 case IntegerType: 00068 mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); 00069 break; 00070 case FractionType: 00071 case FloatType: 00072 case SpecialType: 00073 // What should I do here? 00074 break; 00075 } 00076 } 00077 00078 _knumfraction::_knumfraction(_knumber const & num) 00079 { 00080 mpq_init(_mpq); 00081 00082 switch(num.type()) { 00083 case IntegerType: 00084 mpq_set_z(_mpq, dynamic_cast<_knuminteger const &>(num)._mpz); 00085 break; 00086 case FractionType: 00087 mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); 00088 break; 00089 case FloatType: 00090 case SpecialType: 00091 // What should I do here? 00092 break; 00093 } 00094 } 00095 00096 _knumfloat::_knumfloat(_knumber const & num) 00097 { 00098 mpf_init(_mpf); 00099 00100 switch(num.type()) { 00101 case IntegerType: 00102 mpf_set_z(_mpf, dynamic_cast<_knuminteger const &>(num)._mpz); 00103 break; 00104 case FractionType: 00105 mpf_set_q(_mpf, dynamic_cast<_knumfraction const &>(num)._mpq); 00106 break; 00107 case FloatType: 00108 mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); 00109 break; 00110 case SpecialType: 00111 // What should I do here? 00112 break; 00113 } 00114 } 00115 00116 00117 00118 _knumerror::_knumerror(TQString const & num) 00119 { 00120 if (num == "nan") 00121 _error = UndefinedNumber; 00122 else if (num == "inf") 00123 _error = Infinity; 00124 else if (num == "-inf") 00125 _error = MinusInfinity; 00126 } 00127 00128 _knuminteger::_knuminteger(TQString const & num) 00129 { 00130 mpz_init(_mpz); 00131 mpz_set_str(_mpz, num.ascii(), 10); 00132 } 00133 00134 _knumfraction::_knumfraction(TQString const & num) 00135 { 00136 mpq_init(_mpq); 00137 if (TQRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) { 00138 // my hand-made conversion is terrible 00139 // first me convert the mantissa 00140 unsigned long int digits_after_dot = ((num.section( '.', 1, 1)).section('e', 0, 0)).length(); 00141 TQString tmp_num = num.section('e', 0, 0).remove('.'); 00142 mpq_set_str(_mpq, tmp_num.ascii(), 10); 00143 mpz_t tmp_int; 00144 mpz_init(tmp_int); 00145 mpz_ui_pow_ui (tmp_int, 10, digits_after_dot); 00146 mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); 00147 // now we take care of the exponent 00148 if (! (tmp_num = num.section('e', 1, 1)).isEmpty()) { 00149 long int tmp_exp = tmp_num.toLong(); 00150 if (tmp_exp > 0) { 00151 mpz_ui_pow_ui (tmp_int, 10, 00152 static_cast<unsigned long int>(tmp_exp)); 00153 mpz_mul(mpq_numref(_mpq), mpq_numref(_mpq), tmp_int); 00154 } else { 00155 mpz_ui_pow_ui (tmp_int, 10, 00156 static_cast<unsigned long int>(-tmp_exp)); 00157 mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); 00158 } 00159 } 00160 mpz_clear(tmp_int); 00161 } else 00162 mpq_set_str(_mpq, num.ascii(), 10); 00163 mpq_canonicalize(_mpq); 00164 } 00165 00166 _knumfloat::_knumfloat(TQString const & num) 00167 { 00168 mpf_init(_mpf); 00169 mpf_set_str(_mpf, num.ascii(), 10); 00170 } 00171 00172 _knuminteger const & _knuminteger::operator = (_knuminteger const & num) 00173 { 00174 if (this == &num) 00175 return *this; 00176 00177 mpz_set(_mpz, num._mpz); 00178 return *this; 00179 } 00180 00181 TQString const _knumerror::ascii(int prec) const 00182 { 00183 static_cast<void>(prec); 00184 00185 switch(_error) { 00186 case UndefinedNumber: 00187 return TQString("nan"); 00188 case Infinity: 00189 return TQString("inf"); 00190 case MinusInfinity: 00191 return TQString("-inf"); 00192 default: 00193 return TQString(); 00194 } 00195 } 00196 00197 TQString const _knuminteger::ascii(int prec) const 00198 { 00199 static_cast<void>(prec); 00200 char *tmp_ptr; 00201 00202 gmp_asprintf(&tmp_ptr, "%Zd", _mpz); 00203 TQString ret_str = tmp_ptr; 00204 00205 free(tmp_ptr); 00206 return ret_str; 00207 } 00208 00209 TQString const _knumfraction::ascii(int prec) const 00210 { 00211 static_cast<void>(prec); 00212 char *tmp_ptr = mpq_get_str(0, 10, _mpq); 00213 TQString ret_str = tmp_ptr; 00214 00215 free(tmp_ptr); 00216 00217 return ret_str; 00218 } 00219 00220 TQString const _knumfloat::ascii(int prec) const 00221 { 00222 TQString ret_str; 00223 char *tmp_ptr; 00224 if (prec > 0) 00225 gmp_asprintf(&tmp_ptr, ("%." + TQString(TQString().setNum(prec) + "Fg")).ascii(), _mpf); 00226 else 00227 gmp_asprintf(&tmp_ptr, "%Fg", _mpf); 00228 00229 ret_str = tmp_ptr; 00230 00231 free(tmp_ptr); 00232 00233 return ret_str; 00234 } 00235 00236 00237 bool _knumfraction::isInteger(void) const 00238 { 00239 if (mpz_cmp_ui(mpq_denref(_mpq), 1) == 0) 00240 return true; 00241 else 00242 return false; 00243 } 00244 00245 00246 _knumber * _knumerror::abs(void) const 00247 { 00248 _knumerror * tmp_num = new _knumerror(*this); 00249 00250 if(_error == MinusInfinity) tmp_num->_error = Infinity; 00251 00252 return tmp_num; 00253 } 00254 00255 _knumber * _knuminteger::abs(void) const 00256 { 00257 _knuminteger * tmp_num = new _knuminteger(); 00258 00259 mpz_abs(tmp_num->_mpz, _mpz); 00260 00261 return tmp_num; 00262 } 00263 00264 _knumber * _knumfraction::abs(void) const 00265 { 00266 _knumfraction * tmp_num = new _knumfraction(); 00267 00268 mpq_abs(tmp_num->_mpq, _mpq); 00269 00270 return tmp_num; 00271 } 00272 00273 _knumber * _knumfloat::abs(void) const 00274 { 00275 _knumfloat * tmp_num = new _knumfloat(); 00276 00277 mpf_abs(tmp_num->_mpf, _mpf); 00278 00279 return tmp_num; 00280 } 00281 00282 00283 00284 _knumber * _knumerror::intPart(void) const 00285 { 00286 return new _knumerror(*this); 00287 } 00288 00289 _knumber * _knuminteger::intPart(void) const 00290 { 00291 _knuminteger *tmp_num = new _knuminteger(); 00292 mpz_set(tmp_num->_mpz, _mpz); 00293 return tmp_num; 00294 } 00295 00296 _knumber * _knumfraction::intPart(void) const 00297 { 00298 _knuminteger *tmp_num = new _knuminteger(); 00299 00300 mpz_set_q(tmp_num->_mpz, _mpq); 00301 00302 return tmp_num; 00303 } 00304 00305 _knumber * _knumfloat::intPart(void) const 00306 { 00307 _knuminteger *tmp_num = new _knuminteger(); 00308 00309 mpz_set_f(tmp_num->_mpz, _mpf); 00310 00311 return tmp_num; 00312 } 00313 00314 00315 00316 00317 int _knumerror::sign(void) const 00318 { 00319 switch(_error) { 00320 case Infinity: 00321 return 1; 00322 case MinusInfinity: 00323 return -1; 00324 default: 00325 return 0; 00326 } 00327 } 00328 00329 int _knuminteger::sign(void) const 00330 { 00331 return mpz_sgn(_mpz); 00332 } 00333 00334 int _knumfraction::sign(void) const 00335 { 00336 return mpq_sgn(_mpq); 00337 } 00338 00339 int _knumfloat::sign(void) const 00340 { 00341 return mpf_sgn(_mpf); 00342 } 00343 00344 00345 00346 #warning _cbrt for now this is a stupid work around 00347 static void _cbrt(mpf_t &num) 00348 { 00349 double tmp_num = cbrt(mpf_get_d(num)); 00350 mpf_init_set_d(num, tmp_num); 00351 } 00352 00353 00354 _knumber * _knumerror::cbrt(void) const 00355 { 00356 // infty ^3 = infty; -infty^3 = -infty 00357 _knumerror *tmp_num = new _knumerror(*this); 00358 00359 return tmp_num; 00360 } 00361 00362 _knumber * _knuminteger::cbrt(void) const 00363 { 00364 _knuminteger * tmp_num = new _knuminteger(); 00365 00366 if(mpz_root(tmp_num->_mpz, _mpz, 3)) 00367 return tmp_num; // root is perfect 00368 00369 delete tmp_num; // root was not perfect, result will be float 00370 00371 _knumfloat * tmp_num2 = new _knumfloat(); 00372 mpf_set_z(tmp_num2->_mpf, _mpz); 00373 00374 _cbrt(tmp_num2->_mpf); 00375 00376 return tmp_num2; 00377 } 00378 00379 _knumber * _knumfraction::cbrt(void) const 00380 { 00381 _knumfraction * tmp_num = new _knumfraction(); 00382 if (mpz_root(mpq_numref(tmp_num->_mpq), mpq_numref(_mpq), 3) 00383 && mpz_root(mpq_denref(tmp_num->_mpq), mpq_denref(_mpq), 3)) 00384 return tmp_num; // root is perfect 00385 00386 delete tmp_num; // root was not perfect, result will be float 00387 00388 _knumfloat * tmp_num2 = new _knumfloat(); 00389 mpf_set_q(tmp_num2->_mpf, _mpq); 00390 00391 _cbrt(tmp_num2->_mpf); 00392 00393 return tmp_num2; 00394 } 00395 00396 _knumber * _knumfloat::cbrt(void) const 00397 { 00398 _knumfloat * tmp_num = new _knumfloat(*this); 00399 00400 _cbrt(tmp_num->_mpf); 00401 00402 return tmp_num; 00403 } 00404 00405 00406 00407 00408 _knumber * _knumerror::sqrt(void) const 00409 { 00410 _knumerror *tmp_num = new _knumerror(*this); 00411 00412 if(_error == MinusInfinity) tmp_num->_error = UndefinedNumber; 00413 00414 return tmp_num; 00415 } 00416 00417 _knumber * _knuminteger::sqrt(void) const 00418 { 00419 if (mpz_sgn(_mpz) < 0) { 00420 _knumerror *tmp_num = new _knumerror(UndefinedNumber); 00421 return tmp_num; 00422 } 00423 if (mpz_perfect_square_p(_mpz)) { 00424 _knuminteger * tmp_num = new _knuminteger(); 00425 00426 mpz_sqrt(tmp_num->_mpz, _mpz); 00427 00428 return tmp_num; 00429 } else { 00430 _knumfloat * tmp_num = new _knumfloat(); 00431 mpf_set_z(tmp_num->_mpf, _mpz); 00432 mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); 00433 00434 return tmp_num; 00435 } 00436 } 00437 00438 _knumber * _knumfraction::sqrt(void) const 00439 { 00440 if (mpq_sgn(_mpq) < 0) { 00441 _knumerror *tmp_num = new _knumerror(UndefinedNumber); 00442 return tmp_num; 00443 } 00444 if (mpz_perfect_square_p(mpq_numref(_mpq)) 00445 && mpz_perfect_square_p(mpq_denref(_mpq))) { 00446 _knumfraction * tmp_num = new _knumfraction(); 00447 mpq_set(tmp_num->_mpq, _mpq); 00448 mpz_sqrt(mpq_numref(tmp_num->_mpq), mpq_numref(tmp_num->_mpq)); 00449 mpz_sqrt(mpq_denref(tmp_num->_mpq), mpq_denref(tmp_num->_mpq)); 00450 00451 return tmp_num; 00452 } else { 00453 _knumfloat * tmp_num = new _knumfloat(); 00454 mpf_set_q(tmp_num->_mpf, _mpq); 00455 mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); 00456 00457 return tmp_num; 00458 } 00459 00460 _knumfraction * tmp_num = new _knumfraction(); 00461 00462 return tmp_num; 00463 } 00464 00465 _knumber * _knumfloat::sqrt(void) const 00466 { 00467 if (mpf_sgn(_mpf) < 0) { 00468 _knumerror *tmp_num = new _knumerror(UndefinedNumber); 00469 return tmp_num; 00470 } 00471 _knumfloat * tmp_num = new _knumfloat(); 00472 00473 mpf_sqrt(tmp_num->_mpf, _mpf); 00474 00475 return tmp_num; 00476 } 00477 00478 00479 00480 _knumber * _knumerror::change_sign(void) const 00481 { 00482 _knumerror * tmp_num = new _knumerror(); 00483 00484 if(_error == Infinity) tmp_num->_error = MinusInfinity; 00485 if(_error == MinusInfinity) tmp_num->_error = Infinity; 00486 00487 return tmp_num; 00488 } 00489 00490 _knumber * _knuminteger::change_sign(void) const 00491 { 00492 _knuminteger * tmp_num = new _knuminteger(); 00493 00494 mpz_neg(tmp_num->_mpz, _mpz); 00495 00496 return tmp_num; 00497 } 00498 00499 _knumber * _knumfraction::change_sign(void) const 00500 { 00501 _knumfraction * tmp_num = new _knumfraction(); 00502 00503 mpq_neg(tmp_num->_mpq, _mpq); 00504 00505 return tmp_num; 00506 } 00507 00508 _knumber *_knumfloat::change_sign(void) const 00509 { 00510 _knumfloat * tmp_num = new _knumfloat(); 00511 00512 mpf_neg(tmp_num->_mpf, _mpf); 00513 00514 return tmp_num; 00515 } 00516 00517 00518 _knumber * _knumerror::reciprocal(void) const 00519 { 00520 switch(_error) { 00521 case Infinity: 00522 case MinusInfinity: 00523 return new _knuminteger(0); 00524 case UndefinedNumber: 00525 default: 00526 return new _knumerror(UndefinedNumber); 00527 } 00528 } 00529 00530 _knumber * _knuminteger::reciprocal(void) const 00531 { 00532 if(mpz_cmp_si(_mpz, 0) == 0) return new _knumerror(Infinity); 00533 00534 _knumfraction * tmp_num = new _knumfraction(*this); 00535 00536 mpq_inv(tmp_num->_mpq, tmp_num->_mpq); 00537 00538 return tmp_num; 00539 } 00540 00541 _knumber * _knumfraction::reciprocal() const 00542 { 00543 if(mpq_cmp_si(_mpq, 0, 1) == 0) return new _knumerror(Infinity); 00544 00545 _knumfraction * tmp_num = new _knumfraction(); 00546 00547 mpq_inv(tmp_num->_mpq, _mpq); 00548 00549 return tmp_num; 00550 } 00551 00552 _knumber *_knumfloat::reciprocal(void) const 00553 { 00554 if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); 00555 00556 _knumfloat * tmp_num = new _knumfloat(); 00557 00558 mpf_div(tmp_num->_mpf, _knumfloat("1.0")._mpf, _mpf); 00559 00560 return tmp_num; 00561 } 00562 00563 00564 00565 _knumber * _knumerror::add(_knumber const & arg2) const 00566 { 00567 if (arg2.type() != SpecialType) 00568 return new _knumerror(_error); 00569 00570 _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); 00571 00572 if (_error == UndefinedNumber 00573 || tmp_arg2._error == UndefinedNumber 00574 || (_error == Infinity && tmp_arg2._error == MinusInfinity) 00575 || (_error == MinusInfinity && tmp_arg2._error == Infinity) 00576 ) 00577 return new _knumerror(UndefinedNumber); 00578 00579 return new _knumerror(_error); 00580 } 00581 00582 _knumber * _knuminteger::add(_knumber const & arg2) const 00583 { 00584 if (arg2.type() != IntegerType) 00585 return arg2.add(*this); 00586 00587 _knuminteger * tmp_num = new _knuminteger(); 00588 00589 mpz_add(tmp_num->_mpz, _mpz, 00590 dynamic_cast<_knuminteger const &>(arg2)._mpz); 00591 00592 return tmp_num; 00593 } 00594 00595 _knumber * _knumfraction::add(_knumber const & arg2) const 00596 { 00597 if (arg2.type() == IntegerType) { 00598 // need to cast arg2 to fraction 00599 _knumfraction tmp_num(arg2); 00600 return tmp_num.add(*this); 00601 } 00602 00603 00604 if (arg2.type() == FloatType || arg2.type() == SpecialType) 00605 return arg2.add(*this); 00606 00607 _knumfraction * tmp_num = new _knumfraction(); 00608 00609 mpq_add(tmp_num->_mpq, _mpq, 00610 dynamic_cast<_knumfraction const &>(arg2)._mpq); 00611 00612 return tmp_num; 00613 } 00614 00615 _knumber *_knumfloat::add(_knumber const & arg2) const 00616 { 00617 if (arg2.type() == SpecialType) 00618 return arg2.add(*this); 00619 00620 if (arg2.type() != FloatType) { 00621 // need to cast arg2 to float 00622 _knumfloat tmp_num(arg2); 00623 return tmp_num.add(*this); 00624 } 00625 00626 _knumfloat * tmp_num = new _knumfloat(); 00627 00628 mpf_add(tmp_num->_mpf, _mpf, 00629 dynamic_cast<_knumfloat const &>(arg2)._mpf); 00630 00631 return tmp_num; 00632 } 00633 00634 00635 _knumber * _knumerror::multiply(_knumber const & arg2) const 00636 { 00637 //improve this 00638 switch(arg2.type()) { 00639 case SpecialType: 00640 { 00641 _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); 00642 if (_error == UndefinedNumber || tmp_arg2._error == UndefinedNumber) 00643 return new _knumerror(UndefinedNumber); 00644 if ( this->sign() * arg2.sign() > 0) 00645 return new _knumerror(Infinity); 00646 else 00647 return new _knumerror(MinusInfinity); 00648 } 00649 case IntegerType: 00650 case FractionType: 00651 case FloatType: 00652 { 00653 int sign_arg2 = arg2.sign(); 00654 if (_error == UndefinedNumber || sign_arg2 == 0) 00655 return new _knumerror(UndefinedNumber); 00656 if ( (_error == Infinity && sign_arg2 > 0) || 00657 (_error == MinusInfinity && sign_arg2 < 0) ) 00658 return new _knumerror(Infinity); 00659 00660 return new _knumerror(MinusInfinity); 00661 } 00662 } 00663 00664 return new _knumerror(_error); 00665 } 00666 00667 00668 _knumber * _knuminteger::multiply(_knumber const & arg2) const 00669 { 00670 if (arg2.type() != IntegerType) 00671 return arg2.multiply(*this); 00672 00673 _knuminteger * tmp_num = new _knuminteger(); 00674 00675 mpz_mul(tmp_num->_mpz, _mpz, 00676 dynamic_cast<_knuminteger const &>(arg2)._mpz); 00677 00678 return tmp_num; 00679 } 00680 00681 _knumber * _knumfraction::multiply(_knumber const & arg2) const 00682 { 00683 if (arg2.type() == IntegerType) { 00684 // need to cast arg2 to fraction 00685 _knumfraction tmp_num(arg2); 00686 return tmp_num.multiply(*this); 00687 } 00688 00689 00690 if (arg2.type() == FloatType || arg2.type() == SpecialType) 00691 return arg2.multiply(*this); 00692 00693 _knumfraction * tmp_num = new _knumfraction(); 00694 00695 mpq_mul(tmp_num->_mpq, _mpq, 00696 dynamic_cast<_knumfraction const &>(arg2)._mpq); 00697 00698 return tmp_num; 00699 } 00700 00701 _knumber *_knumfloat::multiply(_knumber const & arg2) const 00702 { 00703 if (arg2.type() == SpecialType) 00704 return arg2.multiply(*this); 00705 if (arg2.type() == IntegerType && 00706 mpz_cmp_si(dynamic_cast<_knuminteger const &>(arg2)._mpz,0) == 0) 00707 // if arg2 == 0 return integer 0!! 00708 return new _knuminteger(0); 00709 00710 if (arg2.type() != FloatType) { 00711 // need to cast arg2 to float 00712 _knumfloat tmp_num(arg2); 00713 return tmp_num.multiply(*this); 00714 } 00715 00716 _knumfloat * tmp_num = new _knumfloat(); 00717 00718 mpf_mul(tmp_num->_mpf, _mpf, 00719 dynamic_cast<_knumfloat const &>(arg2)._mpf); 00720 00721 return tmp_num; 00722 } 00723 00724 00725 00726 00727 00728 _knumber * _knumber::divide(_knumber const & arg2) const 00729 { 00730 _knumber * tmp_num = arg2.reciprocal(); 00731 _knumber * rslt_num = this->multiply(*tmp_num); 00732 00733 delete tmp_num; 00734 00735 return rslt_num; 00736 } 00737 00738 _knumber *_knumfloat::divide(_knumber const & arg2) const 00739 { 00740 if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); 00741 00742 // automatically casts arg2 to float 00743 _knumfloat * tmp_num = new _knumfloat(arg2); 00744 00745 mpf_div(tmp_num->_mpf, _mpf, tmp_num->_mpf); 00746 00747 return tmp_num; 00748 } 00749 00750 00751 00752 00753 _knumber * _knumerror::power(_knumber const & exponent) const 00754 { 00755 static_cast<void>(exponent); 00756 return new _knumerror(UndefinedNumber); 00757 } 00758 00759 _knumber * _knuminteger::power(_knumber const & exponent) const 00760 { 00761 if (exponent.type() == IntegerType) { 00762 00763 mpz_t tmp_mpz; 00764 mpz_init_set(tmp_mpz, 00765 dynamic_cast<_knuminteger const &>(exponent)._mpz); 00766 00767 if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so 00768 // use floats 00769 mpz_clear(tmp_mpz); 00770 // need to cast everything to float 00771 _knumfloat tmp_num1(*this), tmp_num2(exponent); 00772 return tmp_num1.power(tmp_num2); 00773 } 00774 00775 unsigned long int tmp_int = mpz_get_ui(tmp_mpz); 00776 mpz_clear(tmp_mpz); 00777 00778 _knuminteger * tmp_num = new _knuminteger(); 00779 mpz_pow_ui(tmp_num->_mpz, _mpz, tmp_int); 00780 return tmp_num; 00781 } 00782 if (exponent.type() == FractionType) { 00783 if (mpz_sgn(_mpz) < 0) 00784 return new _knumerror(UndefinedNumber); 00785 // GMP only supports few root functions, so we need to convert 00786 // into signed long int 00787 mpz_t tmp_mpz; 00788 mpz_init_set(tmp_mpz, 00789 mpq_denref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); 00790 00791 if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so 00792 // use floats 00793 mpz_clear(tmp_mpz); 00794 // need to cast everything to float 00795 _knumfloat tmp_num1(*this), tmp_num2(exponent); 00796 return tmp_num1.power(tmp_num2); 00797 } 00798 00799 unsigned long int tmp_int = mpz_get_ui(tmp_mpz); 00800 mpz_clear(tmp_mpz); 00801 00802 // first check if result will be an integer 00803 _knuminteger * tmp_num = new _knuminteger(); 00804 int flag = mpz_root(tmp_num->_mpz, _mpz, tmp_int); 00805 if (flag == 0) { // result is not exact 00806 delete tmp_num; 00807 // need to cast everything to float 00808 _knumfloat tmp_num1(*this), tmp_num2(exponent); 00809 return tmp_num1.power(tmp_num2); 00810 } 00811 00812 // result is exact 00813 00814 mpz_init_set(tmp_mpz, 00815 mpq_numref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); 00816 00817 if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so 00818 // use floats 00819 mpz_clear(tmp_mpz); 00820 // need to cast everything to float 00821 _knumfloat tmp_num1(*this), tmp_num2(exponent); 00822 return tmp_num1.power(tmp_num2); 00823 } 00824 tmp_int = mpz_get_ui(tmp_mpz); 00825 mpz_clear(tmp_mpz); 00826 00827 mpz_pow_ui(tmp_num->_mpz, tmp_num->_mpz, tmp_int); 00828 00829 return tmp_num; 00830 } 00831 if (exponent.type() == FloatType) { 00832 // need to cast everything to float 00833 _knumfloat tmp_num(*this); 00834 return tmp_num.power(exponent); 00835 } 00836 00837 return new _knumerror(Infinity); 00838 } 00839 00840 _knumber * _knumfraction::power(_knumber const & exponent) const 00841 { 00842 _knuminteger tmp_num = _knuminteger(); 00843 00844 mpz_set(tmp_num._mpz, mpq_numref(_mpq)); 00845 _knumber *numer = tmp_num.power(exponent); 00846 00847 mpz_set(tmp_num._mpz, mpq_denref(_mpq)); 00848 _knumber *denom = tmp_num.power(exponent); 00849 00850 _knumber *result = numer->divide(*denom); 00851 delete numer; 00852 delete denom; 00853 return result; 00854 } 00855 00856 _knumber * _knumfloat::power(_knumber const & exponent) const 00857 { 00858 return new _knumfloat(pow(static_cast<double>(*this), 00859 static_cast<double>(exponent))); 00860 } 00861 00862 00863 int _knumerror::compare(_knumber const &arg2) const 00864 { 00865 if (arg2.type() != SpecialType) { 00866 switch(_error) { 00867 case Infinity: 00868 return 1; 00869 case MinusInfinity: 00870 return -1; 00871 default: 00872 return 1; // Not really o.k., but what should I return 00873 } 00874 } 00875 00876 switch(_error) { 00877 case Infinity: 00878 if (dynamic_cast<_knumerror const &>(arg2)._error == Infinity) 00879 // Infinity is larger than anything else, but itself 00880 return 0; 00881 return 1; 00882 case MinusInfinity: 00883 if (dynamic_cast<_knumerror const &>(arg2)._error == MinusInfinity) 00884 // MinusInfinity is smaller than anything else, but itself 00885 return 0; 00886 return -1; 00887 default: 00888 if (dynamic_cast<_knumerror const &>(arg2)._error == UndefinedNumber) 00889 // Undefined only equal to itself 00890 return 0; 00891 return -arg2.compare(*this); 00892 } 00893 } 00894 00895 int _knuminteger::compare(_knumber const &arg2) const 00896 { 00897 if (arg2.type() != IntegerType) 00898 return - arg2.compare(*this); 00899 00900 return mpz_cmp(_mpz, dynamic_cast<_knuminteger const &>(arg2)._mpz); 00901 } 00902 00903 int _knumfraction::compare(_knumber const &arg2) const 00904 { 00905 if (arg2.type() != FractionType) { 00906 if (arg2.type() == IntegerType) { 00907 mpq_t tmp_frac; 00908 mpq_init(tmp_frac); 00909 mpq_set_z(tmp_frac, 00910 dynamic_cast<_knuminteger const &>(arg2)._mpz); 00911 int cmp_result = mpq_cmp(_mpq, tmp_frac); 00912 mpq_clear(tmp_frac); 00913 return cmp_result; 00914 } else 00915 return - arg2.compare(*this); 00916 } 00917 00918 return mpq_cmp(_mpq, dynamic_cast<_knumfraction const &>(arg2)._mpq); 00919 } 00920 00921 int _knumfloat::compare(_knumber const &arg2) const 00922 { 00923 if (arg2.type() != FloatType) { 00924 mpf_t tmp_float; 00925 if (arg2.type() == IntegerType) { 00926 mpf_init(tmp_float); 00927 mpf_set_z(tmp_float, 00928 dynamic_cast<_knuminteger const &>(arg2)._mpz); 00929 } else if (arg2.type() == FractionType) { 00930 mpf_init(tmp_float); 00931 mpf_set_q(tmp_float, 00932 dynamic_cast<_knumfraction const &>(arg2)._mpq); 00933 } else 00934 return - arg2.compare(*this); 00935 00936 int cmp_result = mpf_cmp(_mpf, tmp_float); 00937 mpf_clear(tmp_float); 00938 return cmp_result; 00939 } 00940 00941 return mpf_cmp(_mpf, dynamic_cast<_knumfloat const &>(arg2)._mpf); 00942 } 00943 00944 00945 00946 _knumerror::operator signed long int (void) const 00947 { 00948 // what would be the correct return values here? 00949 if (_error == Infinity) 00950 return 0; 00951 if (_error == MinusInfinity) 00952 return 0; 00953 else // if (_error == UndefinedNumber) 00954 return 0; 00955 } 00956 00957 _knumerror::operator unsigned long int (void) const 00958 { 00959 // what would be the correct return values here? 00960 if (_error == Infinity) 00961 return 0; 00962 if (_error == MinusInfinity) 00963 return 0; 00964 else // if (_error == UndefinedNumber) 00965 return 0; 00966 } 00967 00968 00969 _knuminteger::operator signed long int (void) const 00970 { 00971 return mpz_get_si(_mpz); 00972 } 00973 00974 _knumfraction::operator signed long int (void) const 00975 { 00976 return static_cast<signed long int>(mpq_get_d(_mpq)); 00977 } 00978 00979 _knumfloat::operator signed long int (void) const 00980 { 00981 return mpf_get_si(_mpf); 00982 } 00983 00984 _knuminteger::operator unsigned long int (void) const 00985 { 00986 return mpz_get_ui(_mpz); 00987 } 00988 00989 _knumfraction::operator unsigned long int (void) const 00990 { 00991 return static_cast<unsigned long int>(mpq_get_d(_mpq)); 00992 } 00993 00994 _knumfloat::operator unsigned long int (void) const 00995 { 00996 return mpf_get_ui(_mpf); 00997 } 00998 00999 01000 01001 _knumerror::operator double (void) const 01002 { 01003 if (_error == Infinity) 01004 return INFINITY; 01005 if (_error == MinusInfinity) 01006 return -INFINITY; 01007 else // if (_error == UndefinedNumber) 01008 return NAN; 01009 } 01010 01011 _knuminteger::operator double (void) const 01012 { 01013 return mpz_get_d(_mpz); 01014 } 01015 01016 _knumfraction::operator double (void) const 01017 { 01018 return mpq_get_d(_mpq); 01019 } 01020 01021 _knumfloat::operator double (void) const 01022 { 01023 return mpf_get_d(_mpf); 01024 } 01025 01026 01027 01028 01029 _knuminteger * _knuminteger::intAnd(_knuminteger const &arg2) const 01030 { 01031 _knuminteger * tmp_num = new _knuminteger(); 01032 01033 mpz_and(tmp_num->_mpz, _mpz, arg2._mpz); 01034 01035 return tmp_num; 01036 } 01037 01038 _knuminteger * _knuminteger::intOr(_knuminteger const &arg2) const 01039 { 01040 _knuminteger * tmp_num = new _knuminteger(); 01041 01042 mpz_ior(tmp_num->_mpz, _mpz, arg2._mpz); 01043 01044 return tmp_num; 01045 } 01046 01047 _knumber * _knuminteger::mod(_knuminteger const &arg2) const 01048 { 01049 if(mpz_cmp_si(arg2._mpz, 0) == 0) return new _knumerror(UndefinedNumber); 01050 01051 _knuminteger * tmp_num = new _knuminteger(); 01052 01053 mpz_mod(tmp_num->_mpz, _mpz, arg2._mpz); 01054 01055 return tmp_num; 01056 } 01057 01058 _knumber * _knuminteger::shift(_knuminteger const &arg2) const 01059 { 01060 mpz_t tmp_mpz; 01061 01062 mpz_init_set (tmp_mpz, arg2._mpz); 01063 01064 if (! mpz_fits_slong_p(tmp_mpz)) { 01065 mpz_clear(tmp_mpz); 01066 return new _knumerror(UndefinedNumber); 01067 } 01068 01069 signed long int tmp_arg2 = mpz_get_si(tmp_mpz); 01070 mpz_clear(tmp_mpz); 01071 01072 01073 _knuminteger * tmp_num = new _knuminteger(); 01074 01075 if (tmp_arg2 > 0) // left shift 01076 mpz_mul_2exp(tmp_num->_mpz, _mpz, tmp_arg2); 01077 else // right shift 01078 mpz_tdiv_q_2exp(tmp_num->_mpz, _mpz, -tmp_arg2); 01079 01080 01081 return tmp_num; 01082 } 01083