knumber.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <math.h>
00022
00023 #include <config.h>
00024
00025 #include <qregexp.h>
00026 #include <qstring.h>
00027
00028 #include "knumber.h"
00029
00030 KNumber const KNumber::Zero(0);
00031 KNumber const KNumber::One(1);
00032 KNumber const KNumber::MinusOne(-1);
00033 KNumber const KNumber::Pi("3.141592653589793238462643383279502884197169"
00034 "39937510582097494459230781640628620899862803"
00035 "4825342117068");
00036 KNumber const KNumber::Euler("2.718281828459045235360287471352662497757"
00037 "24709369995957496696762772407663035354759"
00038 "4571382178525166427");
00039
00040
00041 bool KNumber::_float_output = false;
00042 bool KNumber::_fraction_input = false;
00043 bool KNumber::_splitoffinteger_output = false;
00044
00045 KNumber::KNumber(signed int num)
00046 {
00047 _num = new _knuminteger(num);
00048 }
00049
00050 KNumber::KNumber(unsigned int num)
00051 {
00052 _num = new _knuminteger(num);
00053 }
00054
00055 KNumber::KNumber(signed long int num)
00056 {
00057 _num = new _knuminteger(num);
00058 }
00059
00060 KNumber::KNumber(unsigned long int num)
00061 {
00062 _num = new _knuminteger(num);
00063 }
00064
00065 KNumber::KNumber(unsigned long long int num)
00066 {
00067 _num = new _knuminteger(num);
00068 }
00069
00070 KNumber::KNumber(double num)
00071 {
00072 if ( isinf(num) ) _num = new _knumerror( _knumber::Infinity );
00073 else if ( isnan(num) ) _num = new _knumerror( _knumber::UndefinedNumber );
00074 else _num = new _knumfloat(num);
00075
00076 }
00077
00078 KNumber::KNumber(KNumber const & num)
00079 {
00080 switch(num.type()) {
00081 case SpecialType:
00082 _num = new _knumerror(*(num._num));
00083 return;
00084 case IntegerType:
00085 _num = new _knuminteger(*(num._num));
00086 return;
00087 case FractionType:
00088 _num = new _knumfraction(*(num._num));
00089 return;
00090 case FloatType:
00091 _num = new _knumfloat(*(num._num));
00092 return;
00093 };
00094 }
00095
00096
00097 KNumber::KNumber(QString const & num)
00098 {
00099 if (QRegExp("^(inf|-inf|nan)$").exactMatch(num))
00100 _num = new _knumerror(num);
00101 else if (QRegExp("^[+-]?\\d+$").exactMatch(num))
00102 _num = new _knuminteger(num);
00103 else if (QRegExp("^[+-]?\\d+/\\d+$").exactMatch(num)) {
00104 _num = new _knumfraction(num);
00105 simplifyRational();
00106 }
00107 else if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num))
00108 if (_fraction_input == true) {
00109 _num = new _knumfraction(num);
00110 simplifyRational();
00111 } else
00112 _num = new _knumfloat(num);
00113 }
00114
00115 KNumber::NumType KNumber::type(void) const
00116 {
00117 if(dynamic_cast<_knumerror *>(_num))
00118 return SpecialType;
00119 if(dynamic_cast<_knuminteger *>(_num))
00120 return IntegerType;
00121 if(dynamic_cast<_knumfraction *>(_num))
00122 return FractionType;
00123 if(dynamic_cast<_knumfloat *>(_num))
00124 return FloatType;
00125
00126 return SpecialType;
00127 }
00128
00129
00130
00131
00132
00133 void KNumber::simplifyRational(void)
00134 {
00135 if (type() != FractionType)
00136 return;
00137
00138 _knumfraction *tmp_num = dynamic_cast<_knumfraction *>(_num);
00139
00140 if (tmp_num->isInteger()) {
00141 _knumber *tmp_num2 = tmp_num->intPart();
00142 delete tmp_num;
00143 _num = tmp_num2;
00144 }
00145
00146 }
00147
00148
00149 KNumber const & KNumber::operator=(KNumber const & num)
00150 {
00151 if (this == & num)
00152 return *this;
00153
00154 delete _num;
00155
00156 switch(num.type()) {
00157 case SpecialType:
00158 _num = new _knumerror();
00159 break;
00160 case IntegerType:
00161 _num = new _knuminteger();
00162 break;
00163 case FractionType:
00164 _num = new _knumfraction();
00165 break;
00166 case FloatType:
00167 _num = new _knumfloat();
00168 break;
00169 };
00170
00171 _num->copy(*(num._num));
00172
00173 return *this;
00174 }
00175
00176 KNumber & KNumber::operator +=(KNumber const &arg)
00177 {
00178 KNumber tmp_num = *this + arg;
00179
00180 delete _num;
00181
00182 switch(tmp_num.type()) {
00183 case SpecialType:
00184 _num = new _knumerror();
00185 break;
00186 case IntegerType:
00187 _num = new _knuminteger();
00188 break;
00189 case FractionType:
00190 _num = new _knumfraction();
00191 break;
00192 case FloatType:
00193 _num = new _knumfloat();
00194 break;
00195 };
00196
00197 _num->copy(*(tmp_num._num));
00198
00199 return *this;
00200 }
00201
00202 KNumber & KNumber::operator -=(KNumber const &arg)
00203 {
00204 KNumber tmp_num = *this - arg;
00205
00206 delete _num;
00207
00208 switch(tmp_num.type()) {
00209 case SpecialType:
00210 _num = new _knumerror();
00211 break;
00212 case IntegerType:
00213 _num = new _knuminteger();
00214 break;
00215 case FractionType:
00216 _num = new _knumfraction();
00217 break;
00218 case FloatType:
00219 _num = new _knumfloat();
00220 break;
00221 };
00222
00223 _num->copy(*(tmp_num._num));
00224
00225 return *this;
00226 }
00227
00228
00229 static void _inc_by_one(QString &str, int position)
00230 {
00231 for (int i = position; i >= 0; i--)
00232 {
00233 char last_char = str[i].latin1();
00234 switch(last_char)
00235 {
00236 case '0':
00237 str[i] = '1';
00238 break;
00239 case '1':
00240 str[i] = '2';
00241 break;
00242 case '2':
00243 str[i] = '3';
00244 break;
00245 case '3':
00246 str[i] = '4';
00247 break;
00248 case '4':
00249 str[i] = '5';
00250 break;
00251 case '5':
00252 str[i] = '6';
00253 break;
00254 case '6':
00255 str[i] = '7';
00256 break;
00257 case '7':
00258 str[i] = '8';
00259 break;
00260 case '8':
00261 str[i] = '9';
00262 break;
00263 case '9':
00264 str[i] = '0';
00265 if (i == 0) str.prepend('1');
00266 continue;
00267 case '.':
00268 continue;
00269 }
00270 break;
00271 }
00272 }
00273
00274
00275 static void _round(QString &str, int precision)
00276 {
00277 int decimalSymbolPos = str.find('.');
00278
00279 if (decimalSymbolPos == -1)
00280 if (precision == 0) return;
00281 else if (precision > 0)
00282 {
00283 str.append('.');
00284 decimalSymbolPos = str.length() - 1;
00285 }
00286
00287
00288 str.append(QString().fill('0', precision));
00289
00290
00291 char last_char = str[decimalSymbolPos + precision + 1].latin1();
00292 switch (last_char)
00293 {
00294 case '0':
00295 case '1':
00296 case '2':
00297 case '3':
00298 case '4':
00299
00300 break;
00301 case '5':
00302 case '6':
00303 case '7':
00304 case '8':
00305 case '9':
00306
00307 _inc_by_one(str, decimalSymbolPos + precision);
00308 break;
00309 default:
00310 break;
00311 }
00312
00313 decimalSymbolPos = str.find('.');
00314 str.truncate(decimalSymbolPos + precision + 1);
00315
00316
00317 if (precision == 0) str = str.section('.', 0, 0);
00318 }
00319
00320 static QString roundNumber(const QString &numStr, int precision)
00321 {
00322 QString tmpString = numStr;
00323 if (precision < 0 ||
00324 ! QRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString))
00325 return numStr;
00326
00327
00328
00329 bool neg = (tmpString[0] == '-');
00330 if (neg || tmpString[0] == '+') tmpString.remove(0, 1);
00331
00332
00333
00334 QString mantString = tmpString.section('e', 0, 0,
00335 QString::SectionCaseInsensitiveSeps);
00336 QString expString = tmpString.section('e', 1, 1,
00337 QString::SectionCaseInsensitiveSeps |
00338 QString::SectionIncludeLeadingSep);
00339 if (expString.length() == 1) expString = QString();
00340
00341
00342 _round(mantString, precision);
00343
00344 if(neg) mantString.prepend('-');
00345
00346 return mantString + expString;
00347 }
00348
00349
00350 QString const KNumber::toQString(int width, int prec) const
00351 {
00352 QString tmp_str;
00353
00354 if (*this == Zero)
00355 return "0";
00356 switch (type()) {
00357 case IntegerType:
00358 if (width > 0) {
00359 bool tmp_bool = _fraction_input;
00360 _fraction_input = false;
00361 tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1);
00362 _fraction_input = tmp_bool;
00363 } else
00364 tmp_str = QString(_num->ascii());
00365 break;
00366 case FractionType:
00367 if (_float_output) {
00368 bool tmp_bool = _fraction_input;
00369 _fraction_input = false;
00370 tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1);
00371 _fraction_input = tmp_bool;
00372 } else {
00373 if(_splitoffinteger_output) {
00374
00375 KNumber int_part = this->integerPart();
00376 if (int_part == Zero)
00377 tmp_str = QString(_num->ascii());
00378 else if (int_part < Zero)
00379 tmp_str = int_part.toQString() + " " + (int_part - *this)._num->ascii();
00380 else
00381 tmp_str = int_part.toQString() + " " + (*this - int_part)._num->ascii();
00382 } else
00383 tmp_str = QString(_num->ascii());
00384
00385 if (width > 0 && tmp_str.length() > width) {
00386
00387 bool tmp_bool = _fraction_input;
00388 _fraction_input = false;
00389 tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1);
00390 _fraction_input = tmp_bool;
00391 }
00392 }
00393
00394 break;
00395 case FloatType:
00396 if (width > 0)
00397 tmp_str = QString(_num->ascii(width));
00398 else
00399
00400 tmp_str = QString(_num->ascii(3*mpf_get_default_prec()/10));
00401 break;
00402 default:
00403 return QString(_num->ascii());
00404 }
00405
00406 if (prec >= 0)
00407 return roundNumber(tmp_str, prec);
00408 else
00409 return tmp_str;
00410 }
00411
00412 void KNumber::setDefaultFloatOutput(bool flag)
00413 {
00414 _float_output = flag;
00415 }
00416
00417 void KNumber::setDefaultFractionalInput(bool flag)
00418 {
00419 _fraction_input = flag;
00420 }
00421
00422 void KNumber::setSplitoffIntegerForFractionOutput(bool flag)
00423 {
00424 _splitoffinteger_output = flag;
00425 }
00426
00427 void KNumber::setDefaultFloatPrecision(unsigned int prec)
00428 {
00429
00430 unsigned long int bin_prec = static_cast<unsigned long int>
00431 (double(prec) * M_LN10 / M_LN2 + 1);
00432
00433 mpf_set_default_prec(bin_prec);
00434 }
00435
00436 KNumber const KNumber::abs(void) const
00437 {
00438 KNumber tmp_num;
00439 delete tmp_num._num;
00440
00441 tmp_num._num = _num->abs();
00442
00443 return tmp_num;
00444 }
00445
00446 KNumber const KNumber::cbrt(void) const
00447 {
00448 KNumber tmp_num;
00449 delete tmp_num._num;
00450
00451 tmp_num._num = _num->cbrt();
00452
00453 return tmp_num;
00454 }
00455
00456 KNumber const KNumber::sqrt(void) const
00457 {
00458 KNumber tmp_num;
00459 delete tmp_num._num;
00460
00461 tmp_num._num = _num->sqrt();
00462
00463 return tmp_num;
00464 }
00465
00466 KNumber const KNumber::integerPart(void) const
00467 {
00468 KNumber tmp_num;
00469 delete tmp_num._num;
00470 tmp_num._num = _num->intPart();
00471
00472 return tmp_num;
00473 }
00474
00475 KNumber const KNumber::power(KNumber const &exp) const
00476 {
00477 if (*this == Zero) {
00478 if(exp == Zero)
00479 return KNumber("nan");
00480 else if (exp < Zero)
00481 return KNumber("inf");
00482 else
00483 return KNumber(0);
00484 }
00485
00486 if (exp == Zero) {
00487 if (*this != Zero)
00488 return One;
00489 else
00490 return KNumber("nan");
00491 }
00492 else if (exp < Zero) {
00493 KNumber tmp_num;
00494 KNumber tmp_num2 = -exp;
00495 delete tmp_num._num;
00496 tmp_num._num = _num->power(*(tmp_num2._num));
00497
00498 return One/tmp_num;
00499 }
00500 else {
00501 KNumber tmp_num;
00502 delete tmp_num._num;
00503 tmp_num._num = _num->power(*(exp._num));
00504
00505 return tmp_num;
00506 }
00507
00508 }
00509
00510 KNumber const KNumber::operator-(void) const
00511 {
00512 KNumber tmp_num;
00513 delete tmp_num._num;
00514
00515 tmp_num._num = _num->change_sign();
00516
00517 return tmp_num;
00518 }
00519
00520 KNumber const KNumber::operator+(KNumber const & arg2) const
00521 {
00522 KNumber tmp_num;
00523 delete tmp_num._num;
00524
00525 tmp_num._num = _num->add(*arg2._num);
00526
00527 tmp_num.simplifyRational();
00528
00529 return tmp_num;
00530 }
00531
00532 KNumber const KNumber::operator-(KNumber const & arg2) const
00533 {
00534 return *this + (-arg2);
00535 }
00536
00537 KNumber const KNumber::operator*(KNumber const & arg2) const
00538 {
00539 KNumber tmp_num;
00540 delete tmp_num._num;
00541
00542 tmp_num._num = _num->multiply(*arg2._num);
00543
00544 tmp_num.simplifyRational();
00545
00546 return tmp_num;
00547 }
00548
00549 KNumber const KNumber::operator/(KNumber const & arg2) const
00550 {
00551 KNumber tmp_num;
00552 delete tmp_num._num;
00553
00554 tmp_num._num = _num->divide(*arg2._num);
00555
00556 tmp_num.simplifyRational();
00557
00558 return tmp_num;
00559 }
00560
00561
00562 KNumber const KNumber::operator%(KNumber const & arg2) const
00563 {
00564 if (type() != IntegerType || arg2.type() != IntegerType)
00565 return Zero;
00566
00567 KNumber tmp_num;
00568 delete tmp_num._num;
00569
00570 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00571 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00572
00573 tmp_num._num = tmp_arg1->mod(*tmp_arg2);
00574
00575 return tmp_num;
00576 }
00577
00578 KNumber const KNumber::operator&(KNumber const & arg2) const
00579 {
00580 if (type() != IntegerType || arg2.type() != IntegerType)
00581 return Zero;
00582
00583 KNumber tmp_num;
00584 delete tmp_num._num;
00585
00586 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00587 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00588
00589 tmp_num._num = tmp_arg1->intAnd(*tmp_arg2);
00590
00591 return tmp_num;
00592
00593 }
00594
00595 KNumber const KNumber::operator|(KNumber const & arg2) const
00596 {
00597 if (type() != IntegerType || arg2.type() != IntegerType)
00598 return Zero;
00599
00600 KNumber tmp_num;
00601 delete tmp_num._num;
00602
00603 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00604 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00605
00606 tmp_num._num = tmp_arg1->intOr(*tmp_arg2);
00607
00608 return tmp_num;
00609 }
00610
00611
00612 KNumber const KNumber::operator<<(KNumber const & arg2) const
00613 {
00614 if (type() != IntegerType || arg2.type() != IntegerType)
00615 return KNumber("nan");
00616
00617 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00618 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00619
00620 KNumber tmp_num;
00621 delete tmp_num._num;
00622 tmp_num._num = tmp_arg1->shift(*tmp_arg2);
00623
00624 return tmp_num;
00625 }
00626
00627 KNumber const KNumber::operator>>(KNumber const & arg2) const
00628 {
00629 if (type() != IntegerType || arg2.type() != IntegerType)
00630 return KNumber("nan");
00631
00632 KNumber tmp_num = -arg2;
00633
00634 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00635 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(tmp_num._num);
00636
00637 KNumber tmp_num2;
00638 delete tmp_num2._num;
00639 tmp_num2._num = tmp_arg1->shift(*tmp_arg2);
00640
00641 return tmp_num2;
00642 }
00643
00644
00645
00646 KNumber::operator bool(void) const
00647 {
00648 if (*this == Zero)
00649 return false;
00650 return true;
00651 }
00652
00653 KNumber::operator signed long int(void) const
00654 {
00655 return static_cast<signed long int>(*_num);
00656 }
00657
00658 KNumber::operator unsigned long int(void) const
00659 {
00660 return static_cast<unsigned long int>(*_num);
00661 }
00662
00663 KNumber::operator unsigned long long int(void) const
00664 {
00665 #if SIZEOF_LONG >= 8
00666 return static_cast<unsigned long int>(*this);
00667 #else
00668
00669 KNumber tmp_num1 = this->abs().integerPart();
00670 unsigned long long int tmp_num2 = static_cast<unsigned long int>(tmp_num1) +
00671 (static_cast<unsigned long long int>(
00672 static_cast<unsigned long int>(tmp_num1 >> KNumber("32"))) << 32) ;
00673
00674 #warning the cast operator from KNumber to unsigned long long int is probably buggy, when a sign is involved
00675 if (*this > KNumber(0))
00676 return tmp_num2;
00677 else
00678 return static_cast<unsigned long long int> (- static_cast<signed long long int>(tmp_num2));
00679
00680 #endif
00681 }
00682
00683 KNumber::operator double(void) const
00684 {
00685 return static_cast<double>(*_num);
00686 }
00687
00688 int const KNumber::compare(KNumber const & arg2) const
00689 {
00690 return _num->compare(*arg2._num);
00691 }
|