checkdouble.h 6.7 KB

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