Advertisement
Guest User

Untitled

a guest
Oct 26th, 2016
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. #include <limits>
  2. #include <iostream>
  3.  
  4.  
  5. using namespace std;
  6. struct overflow_exception {
  7. overflow_exception(string const& text) : message(text) { };
  8. string const& message_text() {
  9. return message;
  10. }
  11. private:
  12. string message;
  13. };
  14.  
  15. struct signed_tag {};
  16. struct unsigned_tag {};
  17.  
  18. template<typename T, bool C>
  19. struct overflow_traits;
  20.  
  21. template<typename T>
  22. struct overflow_traits<T, 1> {
  23. typedef typename signed_tag tag;
  24. };
  25.  
  26. template<typename T>
  27. struct overflow_traits<T, 0> {
  28. typedef typename unsigned_tag tag;
  29. };
  30.  
  31. template<typename T>
  32. struct overflowChecking {
  33. overflowChecking() {};
  34. overflowChecking(T val) : value(val) {};
  35. //---------
  36. //add
  37. //---------
  38. overflowChecking<T> add_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
  39. if ((right.value < 0 && left.value < numeric_limits<T>::min() - right)
  40. || (right.value > 0 && left.value > numeric_limits<T>::max() - right)) {
  41. throw overflow_exception("signed numbers add overflow");
  42. }
  43. return overflowChecking<T>(left.value + right.value);
  44. }
  45. overflowChecking<T> add_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
  46. if (right.value > numeric_limits<T>::max() - left.value) {
  47. throw overflow_exception("unsigned numbers add overflow");
  48. }
  49. return overflowChecking<T>(left.value + right.value);
  50. }
  51. overflowChecking<T> operator+(overflowChecking<T> const& left, overflowChecking<T> const& right) {
  52. return add_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed()>::tag() tag);
  53. }
  54.  
  55. //--------
  56. //sub
  57. //--------
  58. overflowChecking<T> sub_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
  59. if ((right.value > 0 && left.value < numeric_limits<T>::min() + right.value)
  60. || (right.value < 0 && left.value > numeric_limits<T>::max() + right.value)) {
  61. throw overflow_exception("signed numbers subtract overflow");
  62. }
  63. return overflowChecking<T>(left.value + right.value);
  64. }
  65. overflowChecking<T> sub_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
  66. if (right.value > left.value) {
  67. throw overflow_exception("unsigned numbers subtract overflow");
  68. }
  69. return overflowChecking<T>(left.value + right.value);
  70. }
  71. overflowChecking<T> operator-(overflowChecking<T> const& left, overflowChecking<T> const& right) {
  72. return sub_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed()>::tag() tag);
  73. }
  74.  
  75. //--------
  76. //mul
  77. //--------
  78. overflowChecking<T> mul_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
  79. if (left.value != 0 && right.value != 0 && ((left.value == -1 && righ.value == numeric_limits<T>::min())
  80. || (right.value == -1 && left.value == numeric_limits<T>::min())
  81. || (right.value / abs(right.value) == left.value / abs(left.value) &&
  82. abs(right.value) > numeric_limits<T>::max() / abs(left.value))
  83. || (right.value / abs(right.value) != left.value / abs(left.value) &&
  84. right.value > numeric_limits<T>::min() / left.value))) {
  85. throw overflow_exception("singed numbers multiply overflow");
  86. }
  87. return overflowChecking<T>(left.value * right.value);
  88. }
  89. overflowChecking<T> mul_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
  90. if (left.value != 0 && right.value != 0 &&
  91. (left.value > numeric_limits<T>::max() / right.value)) {
  92. throw overflowChecking("unsigned numbers multiply overflow");
  93. }
  94. return overflowChecking<T>(left.value * right.value);
  95. }
  96. overflowChecking<T> operator*(overflowChecking<T> const& left, overflowChecking<T> const& right) {
  97. return mul_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
  98. }
  99.  
  100. //--------
  101. //div
  102. //--------
  103.  
  104. overflowChecking<T> div_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
  105. if (right.value == -1 && left.value == numeric_limits<T>::min()) {
  106. throw overflow_exception("signed numbers division overflow");
  107. }
  108. return overflowChecking<T>(left.value / right.value);
  109. }
  110. overflowChecking<T> div_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
  111. return overflowChecking(left.value / right.value);
  112.  
  113. }
  114. overflowChecking<T> operator/(overflowChecking<T> const& left, overflowChecking<T> const& right) {
  115. return div_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
  116. }
  117.  
  118. overflowChecking<T>& operator=(overflowChecking<T> const& right) {
  119. this->value = right.value;
  120. return *this;
  121. }
  122. overflowChecking<T> negate(signed_tag) const {
  123. if (this->value == numeric_limits<T>::min()) {
  124. throw overflow_exception("signed number negate overflow");
  125. }
  126. this->value = this->value * (T)-1;
  127. return this->value;
  128. }
  129. overflowChecking<T> negate(unsigned_tag) const {
  130. throw overflow_exception("can't negate unsigned number");
  131. }
  132. overflowChecking<T> operator-() const {
  133. return this->negate(typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
  134. }
  135.  
  136. private:
  137. T value;
  138. };
  139.  
  140. int main() {
  141. try {
  142. typedef int8_t type;
  143. {
  144. overflowChecking<type> v1(100);
  145. overflowChecking<type> v2(numeric_limits<type>::min());
  146. v1 + v2;
  147. v1 - v2;
  148. v1 * v2;
  149. v1 / v2;
  150. -v1;
  151. -v2;
  152. }
  153. }
  154. catch (overflow_exception& e) {
  155. cout << e.message_text();
  156. }
  157. return 0;
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement