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