• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdeutils
  • Sitemap
  • Contact Us
 

kcalc

knumber_priv.cpp

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