knumber.cpp
00001 // -*- c-basic-offset: 2 -*- 00002 /* This file is part of the KDE libraries 00003 Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 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 // This method converts a fraction to an integer, whenever possible, 00132 // i.e. 5/1 --> 5 00133 // This method should be called, whenever such a inproper fraction can occur, 00134 // e.g. when adding 4/3 + 2/3.... 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 // increase the digit at 'position' by one 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 // Cut off if more digits in fractional part than 'precision' 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) // add dot if missing (and needed) 00284 { 00285 str.append('.'); 00286 decimalSymbolPos = str.length() - 1; 00287 } 00288 00289 // fill up with more than enough zeroes (in case fractional part too short) 00290 str.append(TQString().fill('0', precision)); 00291 00292 // Now decide whether to round up or down 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 // nothing to do, rounding down 00302 break; 00303 case '5': 00304 case '6': 00305 case '7': 00306 case '8': 00307 case '9': 00308 // rounding up 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 // if precision == 0 delete also '.' 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 // Skip the sign (for now) 00331 bool neg = (tmpString[0] == '-'); 00332 if (neg || tmpString[0] == '+') tmpString.remove(0, 1); 00333 00334 00335 // Split off exponential part (including 'e'-symbol) 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) // important to avoid infinite loops below 00357 return "0"; 00358 switch (type()) { 00359 case IntegerType: 00360 if (width > 0) { //result needs to be cut-off 00361 bool tmp_bool = _fraction_input; // stupid work-around 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; // stupid work-around 00371 _fraction_input = false; 00372 tmp_str = (KNumber("1.0")*(*this)).toTQString(width, -1); 00373 _fraction_input = tmp_bool; 00374 } else { // _float_output == false 00375 if(_splitoffinteger_output) { 00376 // split off integer part 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 //result needs to be cut-off 00389 bool tmp_bool = _fraction_input; // stupid work-around 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 // rough estimate for maximal decimal precision (10^3 = 2^10) 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 // Need to transform decimal digits into binary digits 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"); // 0^0 not defined 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 }