checkdouble.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * File: dclxvi-20130329/checkdouble.h
  3. * Author: Ruben Niederhagen, Peter Schwabe
  4. * Public Domain
  5. */
  6. #ifndef CHECKDOUBLE_H
  7. #define CHECKDOUBLE_H
  8. #include <execinfo.h>
  9. #include <inttypes.h>
  10. #include <memory.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #define MANTISSA_MAX ((1ULL << 53) - 1)
  15. class CheckDouble{
  16. public: double v;
  17. unsigned long long mmax;
  18. CheckDouble()
  19. {
  20. v = NAN;
  21. mmax = MANTISSA_MAX;
  22. }
  23. CheckDouble(const double a)
  24. {
  25. v = a;
  26. mmax = (unsigned long long)fabs(a);
  27. }
  28. CheckDouble(const CheckDouble &a)
  29. {
  30. v = a.v;
  31. mmax = a.mmax;
  32. }
  33. CheckDouble(const double a, const unsigned long long int mmax)
  34. {
  35. v = a;
  36. this->mmax = mmax;
  37. }
  38. CheckDouble operator=(const CheckDouble &a)
  39. {
  40. v = a.v;
  41. mmax = a.mmax;
  42. return *this;
  43. }
  44. int operator==(const CheckDouble &a)const
  45. {
  46. return v == a.v;
  47. }
  48. int operator!=(const CheckDouble &a)const
  49. {
  50. return v != a.v;
  51. }
  52. CheckDouble operator+(const CheckDouble &a)const
  53. {
  54. if((mmax+a.mmax) > MANTISSA_MAX)
  55. {
  56. fprintf(stderr, "Overflow in %lf + %lf\n", v,a.v);
  57. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  58. abort();
  59. }
  60. return CheckDouble(a.v+v, mmax+a.mmax);
  61. }
  62. CheckDouble operator+=(const CheckDouble &a)
  63. {
  64. if((mmax+a.mmax) > MANTISSA_MAX)
  65. {
  66. fprintf(stderr, "Overflow in %lf += %lf\n", v,a.v);
  67. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  68. abort();
  69. }
  70. v += a.v;
  71. mmax += a.mmax;
  72. return *this;
  73. }
  74. CheckDouble operator-(const CheckDouble &a)const
  75. {
  76. if((mmax+a.mmax) > MANTISSA_MAX)
  77. {
  78. fprintf(stderr, "Overflow in %lf - %lf\n", v,a.v);
  79. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  80. abort();
  81. }
  82. return CheckDouble(v-a.v, mmax+a.mmax);
  83. }
  84. CheckDouble operator-=(const CheckDouble &a)
  85. {
  86. if((mmax+a.mmax) > MANTISSA_MAX)
  87. {
  88. fprintf(stderr, "Overflow in %lf += %lf\n", v,a.v);
  89. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  90. abort();
  91. }
  92. v -= a.v;
  93. mmax += a.mmax;
  94. return *this;
  95. }
  96. CheckDouble operator-()const
  97. {
  98. return CheckDouble(-v, mmax);
  99. }
  100. CheckDouble operator*(const CheckDouble &a)const
  101. {
  102. uint64_t l1 = mmax & 0xffffffff;
  103. uint64_t l2 = a.mmax & 0xffffffff;
  104. uint64_t u1 = mmax >> 32;
  105. uint64_t u2 = a.mmax >> 32;
  106. unsigned long long upper = u1 * u2;
  107. if(upper != 0)
  108. {
  109. fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);
  110. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  111. abort();
  112. }
  113. unsigned long long mid = l1 * u2 + u1 * l2;
  114. unsigned long long lower = l1 * l2;
  115. if(lower >= MANTISSA_MAX)
  116. {
  117. fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);
  118. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  119. abort();
  120. }
  121. if(mid > (MANTISSA_MAX>>32))
  122. {
  123. fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);
  124. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  125. abort();
  126. }
  127. lower += (mid <<32);
  128. if(lower > MANTISSA_MAX)
  129. {
  130. fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);
  131. fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);
  132. abort();
  133. }
  134. return CheckDouble(v*a.v, mmax*a.mmax);
  135. }
  136. CheckDouble operator/(const double &a)const
  137. {
  138. if(mmax/fabs(a) > MANTISSA_MAX)
  139. {
  140. fprintf(stderr, "Overflow in %lf / %lf\n", v,a);
  141. fprintf(stderr, "Maximal values: %llu, %lf\n", mmax,a);
  142. abort();
  143. }
  144. return CheckDouble(v/a, mmax/(unsigned long long)fabs(a)+1);
  145. }
  146. CheckDouble operator*=(const int b)
  147. {
  148. CheckDouble op((double) b, abs(b));
  149. *this = *this * op;
  150. return *this;
  151. }
  152. /*
  153. friend CheckDouble operator*(const CheckDouble &a,const int b)
  154. {
  155. CheckDouble op((double) b, abs(b));
  156. return op * a;
  157. }
  158. */
  159. friend CheckDouble operator*(const int32_t b, const CheckDouble &a)
  160. {
  161. CheckDouble op((double) b, abs(b));
  162. return op * a;
  163. }
  164. friend int operator<(const CheckDouble &op1, const CheckDouble &op2)
  165. {
  166. return op1.v < op2.v;
  167. }
  168. friend int operator<=(const CheckDouble &op1, const CheckDouble &op2)
  169. {
  170. return op1.v <= op2.v;
  171. }
  172. friend int operator>(const CheckDouble &op1, const CheckDouble &op2)
  173. {
  174. return op1.v > op2.v;
  175. }
  176. friend int operator>=(const CheckDouble &op1, const CheckDouble &op2)
  177. {
  178. return op1.v >= op2.v;
  179. }
  180. friend CheckDouble round(const CheckDouble &a)
  181. {
  182. return CheckDouble(round(a.v),a.mmax);
  183. }
  184. friend CheckDouble trunc(const CheckDouble &a)
  185. {
  186. return CheckDouble(trunc(a.v),a.mmax);
  187. }
  188. friend CheckDouble remround(const CheckDouble &a, const double d)
  189. {
  190. double carry = round(a.v/d);
  191. return CheckDouble(a.v - carry*d, (unsigned long long)((d+1)/2));
  192. }
  193. friend long long ftoll(const CheckDouble &arg)
  194. {
  195. return (long long)arg.v;
  196. }
  197. friend void setmax(CheckDouble &arg, unsigned long long max)
  198. {
  199. arg.mmax = max;
  200. }
  201. friend double todouble(const CheckDouble &arg)
  202. {
  203. return arg.v;
  204. }
  205. };
  206. int printfoff(...);
  207. #endif // #ifndef CHECKDOUBLE_H