voronoi_robust_fpt.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. // Boost.Polygon library detail/voronoi_robust_fpt.hpp header file
  2. // Copyright Andrii Sydorchuk 2010-2012.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for updates, documentation, and revision history.
  7. #ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
  8. #define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
  9. #include <algorithm>
  10. #include <cmath>
  11. // Geometry predicates with floating-point variables usually require
  12. // high-precision predicates to retrieve the correct result.
  13. // Epsilon robust predicates give the result within some epsilon relative
  14. // error, but are a lot faster than high-precision predicates.
  15. // To make algorithm robust and efficient epsilon robust predicates are
  16. // used at the first step. In case of the undefined result high-precision
  17. // arithmetic is used to produce required robustness. This approach
  18. // requires exact computation of epsilon intervals within which epsilon
  19. // robust predicates have undefined value.
  20. // There are two ways to measure an error of floating-point calculations:
  21. // relative error and ULPs (units in the last place).
  22. // Let EPS be machine epsilon, then next inequalities have place:
  23. // 1 EPS <= 1 ULP <= 2 EPS (1), 0.5 ULP <= 1 EPS <= 1 ULP (2).
  24. // ULPs are good for measuring rounding errors and comparing values.
  25. // Relative errors are good for computation of general relative
  26. // error of formulas or expressions. So to calculate epsilon
  27. // interval within which epsilon robust predicates have undefined result
  28. // next schema is used:
  29. // 1) Compute rounding errors of initial variables using ULPs;
  30. // 2) Transform ULPs to epsilons using upper bound of the (1);
  31. // 3) Compute relative error of the formula using epsilon arithmetic;
  32. // 4) Transform epsilon to ULPs using upper bound of the (2);
  33. // In case two values are inside undefined ULP range use high-precision
  34. // arithmetic to produce the correct result, else output the result.
  35. // Look at almost_equal function to see how two floating-point variables
  36. // are checked to fit in the ULP range.
  37. // If A has relative error of r(A) and B has relative error of r(B) then:
  38. // 1) r(A + B) <= max(r(A), r(B)), for A * B >= 0;
  39. // 2) r(A - B) <= B*r(A)+A*r(B)/(A-B), for A * B >= 0;
  40. // 2) r(A * B) <= r(A) + r(B);
  41. // 3) r(A / B) <= r(A) + r(B);
  42. // In addition rounding error should be added, that is always equal to
  43. // 0.5 ULP or at most 1 epsilon. As you might see from the above formulas
  44. // subtraction relative error may be extremely large, that's why
  45. // epsilon robust comparator class is used to store floating point values
  46. // and compute subtraction as the final step of the evaluation.
  47. // For further information about relative errors and ULPs try this link:
  48. // http://docs.sun.com/source/806-3568/ncg_goldberg.html
  49. namespace boost {
  50. namespace polygon {
  51. namespace detail {
  52. template <typename T>
  53. T get_sqrt(const T& that) {
  54. return (std::sqrt)(that);
  55. }
  56. template <typename T>
  57. bool is_pos(const T& that) {
  58. return that > 0;
  59. }
  60. template <typename T>
  61. bool is_neg(const T& that) {
  62. return that < 0;
  63. }
  64. template <typename T>
  65. bool is_zero(const T& that) {
  66. return that == 0;
  67. }
  68. template <typename _fpt>
  69. class robust_fpt {
  70. public:
  71. typedef _fpt floating_point_type;
  72. typedef _fpt relative_error_type;
  73. // Rounding error is at most 1 EPS.
  74. enum {
  75. ROUNDING_ERROR = 1
  76. };
  77. robust_fpt() : fpv_(0.0), re_(0.0) {}
  78. explicit robust_fpt(floating_point_type fpv) :
  79. fpv_(fpv), re_(0.0) {}
  80. robust_fpt(floating_point_type fpv, relative_error_type error) :
  81. fpv_(fpv), re_(error) {}
  82. floating_point_type fpv() const { return fpv_; }
  83. relative_error_type re() const { return re_; }
  84. relative_error_type ulp() const { return re_; }
  85. robust_fpt& operator=(const robust_fpt& that) {
  86. this->fpv_ = that.fpv_;
  87. this->re_ = that.re_;
  88. return *this;
  89. }
  90. bool has_pos_value() const {
  91. return is_pos(fpv_);
  92. }
  93. bool has_neg_value() const {
  94. return is_neg(fpv_);
  95. }
  96. bool has_zero_value() const {
  97. return is_zero(fpv_);
  98. }
  99. robust_fpt operator-() const {
  100. return robust_fpt(-fpv_, re_);
  101. }
  102. robust_fpt& operator+=(const robust_fpt& that) {
  103. floating_point_type fpv = this->fpv_ + that.fpv_;
  104. if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
  105. (!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
  106. this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
  107. } else {
  108. floating_point_type temp =
  109. (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
  110. if (is_neg(temp))
  111. temp = -temp;
  112. this->re_ = temp + ROUNDING_ERROR;
  113. }
  114. this->fpv_ = fpv;
  115. return *this;
  116. }
  117. robust_fpt& operator-=(const robust_fpt& that) {
  118. floating_point_type fpv = this->fpv_ - that.fpv_;
  119. if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
  120. (!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
  121. this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
  122. } else {
  123. floating_point_type temp =
  124. (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
  125. if (is_neg(temp))
  126. temp = -temp;
  127. this->re_ = temp + ROUNDING_ERROR;
  128. }
  129. this->fpv_ = fpv;
  130. return *this;
  131. }
  132. robust_fpt& operator*=(const robust_fpt& that) {
  133. this->re_ += that.re_ + ROUNDING_ERROR;
  134. this->fpv_ *= that.fpv_;
  135. return *this;
  136. }
  137. robust_fpt& operator/=(const robust_fpt& that) {
  138. this->re_ += that.re_ + ROUNDING_ERROR;
  139. this->fpv_ /= that.fpv_;
  140. return *this;
  141. }
  142. robust_fpt operator+(const robust_fpt& that) const {
  143. floating_point_type fpv = this->fpv_ + that.fpv_;
  144. relative_error_type re;
  145. if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
  146. (!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
  147. re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
  148. } else {
  149. floating_point_type temp =
  150. (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
  151. if (is_neg(temp))
  152. temp = -temp;
  153. re = temp + ROUNDING_ERROR;
  154. }
  155. return robust_fpt(fpv, re);
  156. }
  157. robust_fpt operator-(const robust_fpt& that) const {
  158. floating_point_type fpv = this->fpv_ - that.fpv_;
  159. relative_error_type re;
  160. if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
  161. (!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
  162. re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
  163. } else {
  164. floating_point_type temp =
  165. (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
  166. if (is_neg(temp))
  167. temp = -temp;
  168. re = temp + ROUNDING_ERROR;
  169. }
  170. return robust_fpt(fpv, re);
  171. }
  172. robust_fpt operator*(const robust_fpt& that) const {
  173. floating_point_type fpv = this->fpv_ * that.fpv_;
  174. relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
  175. return robust_fpt(fpv, re);
  176. }
  177. robust_fpt operator/(const robust_fpt& that) const {
  178. floating_point_type fpv = this->fpv_ / that.fpv_;
  179. relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
  180. return robust_fpt(fpv, re);
  181. }
  182. robust_fpt sqrt() const {
  183. return robust_fpt(get_sqrt(fpv_),
  184. re_ * static_cast<relative_error_type>(0.5) +
  185. ROUNDING_ERROR);
  186. }
  187. private:
  188. floating_point_type fpv_;
  189. relative_error_type re_;
  190. };
  191. template <typename T>
  192. robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
  193. return that.sqrt();
  194. }
  195. template <typename T>
  196. bool is_pos(const robust_fpt<T>& that) {
  197. return that.has_pos_value();
  198. }
  199. template <typename T>
  200. bool is_neg(const robust_fpt<T>& that) {
  201. return that.has_neg_value();
  202. }
  203. template <typename T>
  204. bool is_zero(const robust_fpt<T>& that) {
  205. return that.has_zero_value();
  206. }
  207. // robust_dif consists of two not negative values: value1 and value2.
  208. // The resulting expression is equal to the value1 - value2.
  209. // Subtraction of a positive value is equivalent to the addition to value2
  210. // and subtraction of a negative value is equivalent to the addition to
  211. // value1. The structure implicitly avoids difference computation.
  212. template <typename T>
  213. class robust_dif {
  214. public:
  215. robust_dif() :
  216. positive_sum_(0),
  217. negative_sum_(0) {}
  218. explicit robust_dif(const T& value) :
  219. positive_sum_((value > 0)?value:0),
  220. negative_sum_((value < 0)?-value:0) {}
  221. robust_dif(const T& pos, const T& neg) :
  222. positive_sum_(pos),
  223. negative_sum_(neg) {}
  224. T dif() const {
  225. return positive_sum_ - negative_sum_;
  226. }
  227. T pos() const {
  228. return positive_sum_;
  229. }
  230. T neg() const {
  231. return negative_sum_;
  232. }
  233. robust_dif<T> operator-() const {
  234. return robust_dif(negative_sum_, positive_sum_);
  235. }
  236. robust_dif<T>& operator+=(const T& val) {
  237. if (!is_neg(val))
  238. positive_sum_ += val;
  239. else
  240. negative_sum_ -= val;
  241. return *this;
  242. }
  243. robust_dif<T>& operator+=(const robust_dif<T>& that) {
  244. positive_sum_ += that.positive_sum_;
  245. negative_sum_ += that.negative_sum_;
  246. return *this;
  247. }
  248. robust_dif<T>& operator-=(const T& val) {
  249. if (!is_neg(val))
  250. negative_sum_ += val;
  251. else
  252. positive_sum_ -= val;
  253. return *this;
  254. }
  255. robust_dif<T>& operator-=(const robust_dif<T>& that) {
  256. positive_sum_ += that.negative_sum_;
  257. negative_sum_ += that.positive_sum_;
  258. return *this;
  259. }
  260. robust_dif<T>& operator*=(const T& val) {
  261. if (!is_neg(val)) {
  262. positive_sum_ *= val;
  263. negative_sum_ *= val;
  264. } else {
  265. positive_sum_ *= -val;
  266. negative_sum_ *= -val;
  267. swap();
  268. }
  269. return *this;
  270. }
  271. robust_dif<T>& operator*=(const robust_dif<T>& that) {
  272. T positive_sum = this->positive_sum_ * that.positive_sum_ +
  273. this->negative_sum_ * that.negative_sum_;
  274. T negative_sum = this->positive_sum_ * that.negative_sum_ +
  275. this->negative_sum_ * that.positive_sum_;
  276. positive_sum_ = positive_sum;
  277. negative_sum_ = negative_sum;
  278. return *this;
  279. }
  280. robust_dif<T>& operator/=(const T& val) {
  281. if (!is_neg(val)) {
  282. positive_sum_ /= val;
  283. negative_sum_ /= val;
  284. } else {
  285. positive_sum_ /= -val;
  286. negative_sum_ /= -val;
  287. swap();
  288. }
  289. return *this;
  290. }
  291. private:
  292. void swap() {
  293. (std::swap)(positive_sum_, negative_sum_);
  294. }
  295. T positive_sum_;
  296. T negative_sum_;
  297. };
  298. template<typename T>
  299. robust_dif<T> operator+(const robust_dif<T>& lhs,
  300. const robust_dif<T>& rhs) {
  301. return robust_dif<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg());
  302. }
  303. template<typename T>
  304. robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
  305. if (!is_neg(rhs)) {
  306. return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
  307. } else {
  308. return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
  309. }
  310. }
  311. template<typename T>
  312. robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
  313. if (!is_neg(lhs)) {
  314. return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
  315. } else {
  316. return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
  317. }
  318. }
  319. template<typename T>
  320. robust_dif<T> operator-(const robust_dif<T>& lhs,
  321. const robust_dif<T>& rhs) {
  322. return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
  323. }
  324. template<typename T>
  325. robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
  326. if (!is_neg(rhs)) {
  327. return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
  328. } else {
  329. return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
  330. }
  331. }
  332. template<typename T>
  333. robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
  334. if (!is_neg(lhs)) {
  335. return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
  336. } else {
  337. return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
  338. }
  339. }
  340. template<typename T>
  341. robust_dif<T> operator*(const robust_dif<T>& lhs,
  342. const robust_dif<T>& rhs) {
  343. T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
  344. T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
  345. return robust_dif<T>(res_pos, res_neg);
  346. }
  347. template<typename T>
  348. robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
  349. if (!is_neg(val)) {
  350. return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
  351. } else {
  352. return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
  353. }
  354. }
  355. template<typename T>
  356. robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
  357. if (!is_neg(val)) {
  358. return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
  359. } else {
  360. return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
  361. }
  362. }
  363. template<typename T>
  364. robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
  365. if (!is_neg(val)) {
  366. return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
  367. } else {
  368. return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
  369. }
  370. }
  371. // Used to compute expressions that operate with sqrts with predefined
  372. // relative error. Evaluates expressions of the next type:
  373. // sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4.
  374. template <typename _int, typename _fpt, typename _converter>
  375. class robust_sqrt_expr {
  376. public:
  377. enum MAX_RELATIVE_ERROR {
  378. MAX_RELATIVE_ERROR_EVAL1 = 4,
  379. MAX_RELATIVE_ERROR_EVAL2 = 7,
  380. MAX_RELATIVE_ERROR_EVAL3 = 16,
  381. MAX_RELATIVE_ERROR_EVAL4 = 25
  382. };
  383. // Evaluates expression (re = 4 EPS):
  384. // A[0] * sqrt(B[0]).
  385. _fpt eval1(_int* A, _int* B) {
  386. _fpt a = convert(A[0]);
  387. _fpt b = convert(B[0]);
  388. return a * get_sqrt(b);
  389. }
  390. // Evaluates expression (re = 7 EPS):
  391. // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]).
  392. _fpt eval2(_int* A, _int* B) {
  393. _fpt a = eval1(A, B);
  394. _fpt b = eval1(A + 1, B + 1);
  395. if ((!is_neg(a) && !is_neg(b)) ||
  396. (!is_pos(a) && !is_pos(b)))
  397. return a + b;
  398. return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
  399. }
  400. // Evaluates expression (re = 16 EPS):
  401. // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]).
  402. _fpt eval3(_int* A, _int* B) {
  403. _fpt a = eval2(A, B);
  404. _fpt b = eval1(A + 2, B + 2);
  405. if ((!is_neg(a) && !is_neg(b)) ||
  406. (!is_pos(a) && !is_pos(b)))
  407. return a + b;
  408. tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
  409. tB[3] = 1;
  410. tA[4] = A[0] * A[1] * 2;
  411. tB[4] = B[0] * B[1];
  412. return eval2(tA + 3, tB + 3) / (a - b);
  413. }
  414. // Evaluates expression (re = 25 EPS):
  415. // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
  416. // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]).
  417. _fpt eval4(_int* A, _int* B) {
  418. _fpt a = eval2(A, B);
  419. _fpt b = eval2(A + 2, B + 2);
  420. if ((!is_neg(a) && !is_neg(b)) ||
  421. (!is_pos(a) && !is_pos(b)))
  422. return a + b;
  423. tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
  424. A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
  425. tB[0] = 1;
  426. tA[1] = A[0] * A[1] * 2;
  427. tB[1] = B[0] * B[1];
  428. tA[2] = A[2] * A[3] * -2;
  429. tB[2] = B[2] * B[3];
  430. return eval3(tA, tB) / (a - b);
  431. }
  432. private:
  433. _int tA[5];
  434. _int tB[5];
  435. _converter convert;
  436. };
  437. } // detail
  438. } // polygon
  439. } // boost
  440. #endif // BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT