annotate DEPENDENCIES/generic/include/boost/polygon/detail/voronoi_robust_fpt.hpp @ 125:34e428693f5d vext

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