• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kcalc/knumber
 

kcalc/knumber

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 

kcalc/knumber

Skip menu "kcalc/knumber"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kcalc/knumber

Skip menu "kcalc/knumber"
  • kcalc
  •   knumber
  • superkaramba
Generated for kcalc/knumber by doxygen 1.6.3
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |