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