rvm 1.08
|
00001 #include "config.h" 00002 00003 #include "error.h" 00004 #include "rmath.h" 00005 00006 /** A small set of numeric limits routines, since gcc prior to 3.x doesn't 00007 * have numeric_limits */ 00008 00009 // --------------------------------------------------------------------------- 00010 00011 /** Find the maximum limit for a type, equivalent to 00012 * std::numeric_limits<T>.max() for systems that don't have the limits c++ 00013 * header file. */ 00014 // template<typename T> 00015 // static const T max_limit() 00016 // { 00017 // T tmp = 0; 00018 // static T max = 0; 00019 // static bool found = false; 00020 // 00021 // if (found) { 00022 // return(max); 00023 // } 00024 // 00025 // tmp = 1; 00026 // max = 0; 00027 // while (tmp > max) { 00028 // max = tmp; 00029 // try { 00030 // tmp = (tmp * T(2)) + T(1); 00031 // } 00032 // catch(...) { } 00033 // } 00034 // found = true; 00035 // return(max); 00036 // } 00037 00038 /** Find the maximum limit for a type, equivalent to 00039 * std::numeric_limits<T>.min() for systems that don't have the limits c++ 00040 * header file. 00041 */ 00042 // template<typename T> 00043 // static const T min_limit() 00044 // { 00045 // T tmp = 0; 00046 // static T min = 0; 00047 // static bool found = false; 00048 // 00049 // if (found) { 00050 // return(min); 00051 // } 00052 // 00053 // tmp = -1; 00054 // min = 0; 00055 // while (tmp < min) { 00056 // min = tmp; 00057 // try { 00058 // tmp = (tmp * T(2)) - T(1); 00059 // } 00060 // catch(...) { } 00061 // } 00062 // 00063 // try { 00064 // tmp = - max_limit<T>() - T(1); 00065 // } 00066 // catch(...) { } 00067 // if (tmp < min) { 00068 // min = tmp; 00069 // } 00070 // 00071 // found = true; 00072 // return(min); 00073 // } 00074 00075 /** Return the largest possible number that a float may hold. */ 00076 #ifdef OSX_WORKAROUND 00077 template<> 00078 const float max_limit<float>() 00079 { 00080 return(FLT_MAX); 00081 } 00082 #endif 00083 00084 /** Return the smallest positive number that a float may hold. 00085 * 00086 * Caveat: This is in contrast to other types, where min_limit<T>() will return 00087 * either 0 or the largest possible negative number that the type may hold. If 00088 * you are looking for the largest possible negative number for any given type, 00089 * use lowest_value<T>() instead. 00090 */ 00091 #ifdef OSX_WORKAROUND 00092 template<> 00093 const float min_limit<float>() 00094 { 00095 return(FLT_MIN); 00096 } 00097 #endif 00098 00099 /** Return the largest possible number that a double may hold. */ 00100 #ifdef OSX_WORKAROUND 00101 template<> 00102 const double max_limit<double>() 00103 { 00104 return(DBL_MAX); 00105 } 00106 #endif 00107 00108 /** Return the smallest positive number that a double may hold. 00109 * 00110 * Caveat: This is in contrast to other types, where min_limit<T>() will return 00111 * either 0 or the largest possible negative number that the type may hold. If 00112 * you are looking for the largest possible negative number for any given type, 00113 * use lowest_value<T>() instead. 00114 */ 00115 #ifdef OSX_WORKAROUND 00116 template<> 00117 const double min_limit<double>() 00118 { 00119 return(DBL_MIN); 00120 } 00121 #endif 00122 00123 // --------------------------------------------------------------------------- 00124 00125 /** Return the max_limit of a variable. 00126 * 00127 * This is handy to have because it means 00128 * that the author may change the type of a variable without having to track 00129 * down all uses of max_limit or min_limit to change the type they measure. 00130 */ 00131 // template<typename T> 00132 // static const T max_limit(const T& a_arg) 00133 // { 00134 // T value; 00135 // 00136 // value = max_limit<T>(); 00137 // 00138 // return(value); 00139 // } 00140 00141 /** Return the min_limit of a variable. 00142 * 00143 * This is handy to have because it means 00144 * that the author may change the type of a variable without having to track 00145 * down all uses of max_limit or min_limit to change the type they measure. 00146 */ 00147 // template<typename T> 00148 // static const T min_limit(const T& a_arg) 00149 // { 00150 // T value; 00151 // 00152 // value = min_limit<T>(); 00153 // 00154 // return(value); 00155 // } 00156 00157 // --------------------------------------------------------------------------- 00158 00159 /** Return the maximum possible value a type may hold. 00160 * 00161 * This is just a convenience function to match lowest_value<T>(). All it does 00162 * is return the value of max_limit<T>(). 00163 */ 00164 // template<typename T> 00165 // static const T highest_value(void) 00166 // { 00167 // T value; 00168 // 00169 // value = max_limit<T>(); 00170 // 00171 // return(value); 00172 // } 00173 00174 /** Return the maximum possible value of a variable. */ 00175 // template<typename T> 00176 // static const T highest_value(const T& a_arg) 00177 // { 00178 // T value; 00179 // 00180 // value = highest_value<T>(); 00181 // 00182 // return(value); 00183 // } 00184 00185 /** Return 0 for unsigned types, or the maximum negative value that the type 00186 * may hold. 00187 */ 00188 // template<typename T> 00189 // static const T lowest_value(void) 00190 // { 00191 // T value; 00192 // 00193 // value = -max_limit<T>(); 00194 // if (value > min_limit<T>()) 00195 // value = min_limit<T>(); 00196 // 00197 // return(value); 00198 // } 00199 00200 /** Return 0 for unsigned types, or the maximum negative value that a variable 00201 * may hold. 00202 */ 00203 // template<typename T> 00204 // static const T lowest_value(const T& a_arg) 00205 // { 00206 // T value; 00207 // 00208 // value = lowest_value<T>(); 00209 // 00210 // return(value); 00211 // } 00212 00213 // --------------------------------------------------------------------------- 00214 00215 /** Return the absolute value of a numeric type 00216 * 00217 * Caveat: For some types, the maximum negative value is one larger than the 00218 * maximum positive value: specifically char. Depending on the type and value, 00219 * it may be impossible to return the absolute value. For such types under 00220 * such circumstances an exception is thrown. 00221 */ 00222 // template<typename T> 00223 // T absolute(const T& a_num) 00224 // { 00225 // T num; 00226 // std::string es; 00227 // 00228 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") : BEGIN" << std::endl; 00229 // num = a_num; 00230 // if ((num < 0) && (num == min_limit<T>())) { 00231 // TRY_nomem(es = "Absolute value is not containable by this type: "); 00232 // if (is_char(num)) { 00233 // TRY_nomem(es += estring(static_cast<int>(num))); 00234 // } 00235 // else { 00236 // TRY_nomem(es += estring(num)); 00237 // } 00238 // throw(ERROR(0,es)); 00239 // } 00240 // if (num < 0) { 00241 // num = -num; 00242 // if (num < 0) { 00243 // TRY_nomem(es = "Absolute value is still negative: "); 00244 // if (is_char(num)) { 00245 // TRY_nomem(es += estring(static_cast<int>(num))); 00246 // } 00247 // else { 00248 // TRY_nomem(es += estring(num)); 00249 // } 00250 // throw(INTERNAL_ERROR(0,es)); 00251 // } 00252 // // else std::cerr << "absolute(" << static_cast<long long>(a_num) << ") >= 0" << std::endl; 00253 // } 00254 // 00255 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") = " << static_cast<long long>(num) << std::endl; 00256 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") : END" << std::endl; 00257 // return(num); 00258 // } 00259 00260 // --------------------------------------------------------------------------- 00261 00262 /** Safely manipulate numbers without worryiung about over/underflow error */ 00263 // template<typename T> 00264 // class safe_num 00265 // { 00266 // public: 00267 // /** C'tor */ 00268 // safe_num() 00269 // { 00270 // clear(); 00271 // } 00272 // 00273 // /** C'tor */ 00274 // safe_num(const T a_num) 00275 // { 00276 // clear(); 00277 // m_num = a_num; 00278 // } 00279 // 00280 // /** C'tor */ 00281 // safe_num(const safe_num& a_class) 00282 // { 00283 // clear(); 00284 // m_num = a_class.value(); 00285 // } 00286 // 00287 // /** Clear the value */ 00288 // void clear(void) 00289 // { 00290 // m_num = static_cast<T>(0); 00291 // } 00292 // 00293 // /** Return the value */ 00294 // const T value(void) const 00295 // { 00296 // return(m_num); 00297 // } 00298 // 00299 // /** Assign a value */ 00300 // void assign(const T& a_arg) 00301 // { 00302 // m_num = a_arg; 00303 // } 00304 // 00305 // /** Add a value */ 00306 // void add(const T& a_arg) 00307 // { 00308 // bool overflow = false; 00309 // T num; 00310 // 00311 // if (a_arg < static_cast<T>(0)) { 00312 // num = absolute(a_arg); 00313 // subtract(num); 00314 // return; 00315 // } 00316 // 00317 // if (highest_value<T>() - a_arg < m_num) 00318 // overflow = true; 00319 // 00320 // if (overflow) { 00321 // estring es; 00322 // 00323 // es = "Addition overflow error detected: "; 00324 // if (is_char(m_num)) 00325 // es += estring(static_cast<int>(m_num)); 00326 // else 00327 // es += estring(m_num); 00328 // es += " + "; 00329 // if (is_char(a_arg)) 00330 // es += estring(static_cast<int>(a_arg)); 00331 // else 00332 // es += estring(a_arg); 00333 // throw(INTERNAL_ERROR(0,es)); 00334 // } 00335 // m_num += a_arg; 00336 // } 00337 // 00338 // /** Subtract a value */ 00339 // void subtract(const T& a_arg) 00340 // { 00341 // bool underflow = false; 00342 // T num; 00343 // 00344 // if (a_arg < static_cast<T>(0)) { 00345 // num = absolute(a_arg); 00346 // add(num); 00347 // return; 00348 // } 00349 // 00350 // if (lowest_value<T>() < 0) { 00351 // if (m_num < lowest_value<T>() + a_arg) 00352 // underflow = true; 00353 // } 00354 // else { 00355 // if (m_num - lowest_value<T>() < a_arg) 00356 // underflow = true; 00357 // } 00358 // 00359 // if (underflow) { 00360 // estring es; 00361 // 00362 // es = "Subtraction underflow error detected: "; 00363 // if (is_char(m_num)) 00364 // es += estring(static_cast<int>(m_num)); 00365 // else 00366 // es += estring(m_num); 00367 // es += " - "; 00368 // if (is_char(a_arg)) 00369 // es += estring(static_cast<int>(a_arg)); 00370 // else 00371 // es += estring(a_arg); 00372 // throw(INTERNAL_ERROR(0,es)); 00373 // } 00374 // m_num -= a_arg; 00375 // } 00376 // 00377 // /** Multiply by a value */ 00378 // void multiply(const T& a_arg) 00379 // { 00380 // bool overflow = false; 00381 // 00382 // if ((a_arg == 0) || (m_num == 0) || (a_arg == 1) || (m_num == 1)) { 00383 // m_num *= a_arg; 00384 // return; 00385 // } 00386 // 00387 // if ((lowest_value<T>() < 0) && (m_num < 0) && (a_arg < 0)) { 00388 // if (-highest_value<T>() > a_arg) 00389 // overflow = true; 00390 // if (-(highest_value<T>() / a_arg) < -m_num) 00391 // overflow = true; 00392 // } 00393 // else 00394 // if ((lowest_value<T>() < 0) && (m_num < 0) && (a_arg >= 0)) { 00395 // if (lowest_value<T>() / a_arg > m_num) 00396 // overflow = true; 00397 // } 00398 // else 00399 // if ((lowest_value<T>() < 0) && (m_num >= 0) && (a_arg < 0)) { 00400 // if (lowest_value<T>() / m_num > a_arg) 00401 // overflow = true; 00402 // } 00403 // else 00404 // if ((lowest_value<T>() < 0) && (m_num >= 0) && (a_arg >= 0)) { 00405 // if (highest_value<T>() / a_arg < m_num) 00406 // overflow = true; 00407 // } 00408 // else 00409 // if ((lowest_value<T>() >= 0) && (m_num >= 0) && (a_arg >= 0)) { 00410 // if (highest_value<T>() / a_arg < m_num) 00411 // overflow = true; 00412 // } 00413 // else { 00414 // // This should never happen 00415 // ASSERT(0); 00416 // } 00417 // 00418 // if (overflow) { 00419 // estring es; 00420 // 00421 // es = "Multiplication overflow error detected: "; 00422 // if (is_char(m_num)) 00423 // es += estring(static_cast<int>(m_num)); 00424 // else 00425 // es += estring(m_num); 00426 // es += " * "; 00427 // if (is_char(a_arg)) 00428 // es += estring(static_cast<int>(a_arg)); 00429 // else 00430 // es += estring(a_arg); 00431 // throw(INTERNAL_ERROR(0,es)); 00432 // } 00433 // m_num *= a_arg; 00434 // } 00435 // 00436 // /** Divide by a value */ 00437 // void divide(const T& a_arg) 00438 // { 00439 // T num; 00440 // 00441 // if (a_arg == static_cast<T>(0)) { 00442 // estring es; 00443 // 00444 // es = "Division by zero error detected: "; 00445 // if (is_char(m_num)) 00446 // es += estring(static_cast<int>(m_num)); 00447 // else 00448 // es += estring(m_num); 00449 // es += " / "; 00450 // if (is_char(a_arg)) 00451 // es += estring(static_cast<int>(a_arg)); 00452 // else 00453 // es += estring(a_arg); 00454 // throw(INTERNAL_ERROR(0,es)); 00455 // } 00456 // 00457 // num = m_num; 00458 // num /= a_arg; 00459 // if ((m_num < 0) && (a_arg < 0) && (num < 0)) { 00460 // estring es; 00461 // 00462 // es = "Division result has incorrect sign: "; 00463 // if (is_char(m_num)) 00464 // es += estring(static_cast<int>(m_num)); 00465 // else 00466 // es += estring(m_num); 00467 // es += " / "; 00468 // if (is_char(a_arg)) 00469 // es += estring(static_cast<int>(a_arg)); 00470 // else 00471 // es += estring(a_arg); 00472 // es += " != "; 00473 // if (is_char(num)) 00474 // es += estring(static_cast<int>(num)); 00475 // else 00476 // es += estring(num); 00477 // throw(INTERNAL_ERROR(0,es)); 00478 // } 00479 // 00480 // m_num = num; 00481 // return; 00482 // } 00483 // 00484 // /** Assign a safe_num */ 00485 // void assign(const safe_num<T>& a_class) 00486 // { 00487 // assign(a_class.value()); 00488 // } 00489 // 00490 // /** Add a safe_num */ 00491 // void add(const safe_num<T>& a_class) 00492 // { 00493 // add(a_class.value()); 00494 // } 00495 // 00496 // /** Subtract a safe_num */ 00497 // void subtract(const safe_num<T>& a_class) 00498 // { 00499 // subtract(a_class.value()); 00500 // } 00501 // 00502 // /** Multiply by a safe_num */ 00503 // void multiply(const safe_num<T>& a_class) 00504 // { 00505 // multiply(a_class.value()); 00506 // } 00507 // 00508 // /** Divide by a safe_num */ 00509 // void divide(const safe_num<T>& a_class) 00510 // { 00511 // divide(a_class.value()); 00512 // } 00513 // 00514 // /** Boolean operator */ 00515 // const bool operator==(const T& a_arg) const 00516 // { 00517 // bool value; 00518 // 00519 // value = (m_num == a_arg); 00520 // 00521 // return(value); 00522 // } 00523 // 00524 // /** Boolean operator */ 00525 // const bool operator==(const safe_num<T>& a_class) const 00526 // { 00527 // bool value; 00528 // 00529 // value = (m_num == a_class.value()); 00530 // 00531 // return(value); 00532 // } 00533 // 00534 // /** Boolean operator */ 00535 // const bool operator!=(const T& a_arg) const 00536 // { 00537 // bool value; 00538 // 00539 // value = (m_num != a_arg); 00540 // 00541 // return(value); 00542 // } 00543 // 00544 // /** Boolean operator */ 00545 // const bool operator!=(const safe_num<T>& a_class) const 00546 // { 00547 // bool value; 00548 // 00549 // value = (m_num != a_class.value()); 00550 // 00551 // return(value); 00552 // } 00553 // 00554 // /** Boolean operator */ 00555 // const bool operator<(const T& a_arg) const 00556 // { 00557 // bool value; 00558 // 00559 // value = (m_num < a_arg); 00560 // 00561 // return(value); 00562 // } 00563 // 00564 // /** Boolean operator */ 00565 // const bool operator<(const safe_num<T>& a_class) const 00566 // { 00567 // bool value; 00568 // 00569 // value = (m_num < a_class.value()); 00570 // 00571 // return(value); 00572 // } 00573 // 00574 // /** Boolean operator */ 00575 // const bool operator>(const T& a_arg) const 00576 // { 00577 // bool value; 00578 // 00579 // value = (m_num > a_arg); 00580 // 00581 // return(value); 00582 // } 00583 // 00584 // /** Boolean operator */ 00585 // const bool operator>(const safe_num<T>& a_class) const 00586 // { 00587 // bool value; 00588 // 00589 // value = (m_num > a_class.value()); 00590 // 00591 // return(value); 00592 // } 00593 // 00594 // /** Boolean operator */ 00595 // const bool operator<=(const T& a_arg) const 00596 // { 00597 // bool value; 00598 // 00599 // value = (m_num <= a_arg); 00600 // 00601 // return(value); 00602 // } 00603 // 00604 // /** Boolean operator */ 00605 // const bool operator<=(const safe_num<T>& a_class) const 00606 // { 00607 // bool value; 00608 // 00609 // value = (m_num <= a_class.value()); 00610 // 00611 // return(value); 00612 // } 00613 // 00614 // /** Boolean operator */ 00615 // const bool operator>=(const T& a_arg) const 00616 // { 00617 // bool value; 00618 // 00619 // value = (m_num >= a_arg); 00620 // 00621 // return(value); 00622 // } 00623 // 00624 // /** Boolean operator */ 00625 // const bool operator>=(const safe_num<T>& a_class) const 00626 // { 00627 // bool value; 00628 // 00629 // value = (m_num >= a_class.value()); 00630 // 00631 // return(value); 00632 // } 00633 // 00634 // /** Arithmetic operator */ 00635 // safe_num<T>& operator+=(safe_num<T> a_class) 00636 // { 00637 // add(a_class); 00638 // 00639 // return(*this); 00640 // } 00641 // 00642 // /** Arithmetic operator */ 00643 // safe_num<T>& operator-=(safe_num<T> a_class) 00644 // { 00645 // subtract(a_class); 00646 // 00647 // return(*this); 00648 // } 00649 // 00650 // /** Arithmetic operator */ 00651 // safe_num<T>& operator*=(safe_num<T> a_class) 00652 // { 00653 // multiply(a_class); 00654 // 00655 // return(*this); 00656 // } 00657 // 00658 // /** Arithmetic operator */ 00659 // safe_num<T>& operator/=(safe_num<T> a_class) 00660 // { 00661 // divide(a_class); 00662 // 00663 // return(*this); 00664 // } 00665 // 00666 // /** Arithmetic operator */ 00667 // safe_num<T>& operator%=(safe_num<T> a_class) 00668 // { 00669 // m_num %= a_class.value(); 00670 // 00671 // return(*this); 00672 // } 00673 // 00674 // private: 00675 // T m_num; 00676 // }; 00677 00678 /** Arithmetic operator */ 00679 // template<typename T> 00680 // safe_num<T> operator+(safe_num<T> a_class1, safe_num<T> a_class2) 00681 // { 00682 // safe_num<T> result; 00683 // 00684 // result.assign(a_class1); 00685 // result.add(a_class2); 00686 // 00687 // return(result); 00688 // } 00689 00690 /** Arithmetic operator */ 00691 // template<typename T> 00692 // safe_num<T> operator-(safe_num<T> a_class1, safe_num<T> a_class2) 00693 // { 00694 // safe_num<T> result; 00695 // 00696 // result.assign(a_class1); 00697 // result.subtract(a_class2); 00698 // 00699 // return(result); 00700 // } 00701 00702 /** Arithmetic operator */ 00703 // template<typename T> 00704 // safe_num<T> operator*(safe_num<T> a_class1, safe_num<T> a_class2) 00705 // { 00706 // safe_num<T> result; 00707 // 00708 // result.assign(a_class1); 00709 // result.multiply(a_class2); 00710 // 00711 // return(result); 00712 // } 00713 00714 /** Arithmetic operator */ 00715 // template<typename T> 00716 // safe_num<T> operator/(safe_num<T> a_class1, safe_num<T> a_class2) 00717 // { 00718 // safe_num<T> result; 00719 // 00720 // result.assign(a_class1); 00721 // result.divide(a_class2); 00722 // 00723 // return(result); 00724 // } 00725 00726 /** Arithmetic operator */ 00727 // template<typename T> 00728 // safe_num<T> operator%(safe_num<T> a_class1, safe_num<T> a_class2) 00729 // { 00730 // safe_num<T> result; 00731 // 00732 // result.assign(a_class1.value() % a_class2.value()); 00733 // 00734 // return(result); 00735 // } 00736 00737 /** Arithmetic operator */ 00738 // template<typename T> 00739 // safe_num<T>& operator++(safe_num<T>& a_class) 00740 // { 00741 // a_class.add(static_cast<T>(1)); 00742 // 00743 // return(a_class); 00744 // } 00745 00746 /** Arithmetic operator */ 00747 // template<typename T> 00748 // safe_num<T> operator++(safe_num<T>& a_class, int) 00749 // { 00750 // safe_num<T> result; 00751 // 00752 // result.assign(a_class); 00753 // a_class.add(static_cast<T>(1)); 00754 // 00755 // return(result); 00756 // } 00757 00758 /** Arithmetic operator */ 00759 // template<typename T> 00760 // safe_num<T>& operator--(safe_num<T>& a_class) 00761 // { 00762 // a_class.subtract(static_cast<T>(1)); 00763 // 00764 // return(a_class); 00765 // } 00766 00767 /** Arithmetic operator */ 00768 // template<typename T> 00769 // safe_num<T> operator--(safe_num<T>& a_class, int) 00770 // { 00771 // safe_num<T> result; 00772 // 00773 // result.assign(a_class); 00774 // a_class.subtract(static_cast<T>(1)); 00775 // 00776 // return(result); 00777 // } 00778 00779 /** Arithmetic operator */ 00780 // template<typename T> 00781 // std::ostream& operator<<(std::ostream& a_out, safe_num<T> a_class) 00782 // { 00783 // a_out << a_class.value(); 00784 // 00785 // return(a_out); 00786 // } 00787 00788 /** Arithmetic operator */ 00789 // template<typename T> 00790 // std::istream& operator>>(std::istream& a_in, safe_num<T>& a_class) 00791 // { 00792 // T num; 00793 // 00794 // a_in >> num; 00795 // a_class = num; 00796 // 00797 // return(a_in); 00798 // } 00799 00800 // --------------------------------------------------------------------------- 00801