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