File indexing completed on 2025-12-16 10:04:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
0011 #define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
0012
0013 #include <algorithm>
0014 #include <cmath>
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 namespace boost {
0056 namespace polygon {
0057 namespace detail {
0058
0059 template <typename T>
0060 T get_sqrt(const T& that) {
0061 return (std::sqrt)(that);
0062 }
0063
0064 template <typename T>
0065 bool is_pos(const T& that) {
0066 return that > 0;
0067 }
0068
0069 template <typename T>
0070 bool is_neg(const T& that) {
0071 return that < 0;
0072 }
0073
0074 template <typename T>
0075 bool is_zero(const T& that) {
0076 return that == 0;
0077 }
0078
0079 template <typename _fpt>
0080 class robust_fpt {
0081 public:
0082 typedef _fpt floating_point_type;
0083 typedef _fpt relative_error_type;
0084
0085
0086 enum {
0087 ROUNDING_ERROR = 1
0088 };
0089
0090 robust_fpt() : fpv_(0.0), re_(0.0) {}
0091 explicit robust_fpt(floating_point_type fpv) :
0092 fpv_(fpv), re_(0.0) {}
0093 robust_fpt(floating_point_type fpv, relative_error_type error) :
0094 fpv_(fpv), re_(error) {}
0095
0096 floating_point_type fpv() const { return fpv_; }
0097 relative_error_type re() const { return re_; }
0098 relative_error_type ulp() const { return re_; }
0099
0100 bool has_pos_value() const {
0101 return is_pos(fpv_);
0102 }
0103
0104 bool has_neg_value() const {
0105 return is_neg(fpv_);
0106 }
0107
0108 bool has_zero_value() const {
0109 return is_zero(fpv_);
0110 }
0111
0112 robust_fpt operator-() const {
0113 return robust_fpt(-fpv_, re_);
0114 }
0115
0116 robust_fpt& operator+=(const robust_fpt& that) {
0117 floating_point_type fpv = this->fpv_ + that.fpv_;
0118 if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
0119 (!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
0120 this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
0121 } else {
0122 floating_point_type temp =
0123 (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
0124 if (is_neg(temp))
0125 temp = -temp;
0126 this->re_ = temp + ROUNDING_ERROR;
0127 }
0128 this->fpv_ = fpv;
0129 return *this;
0130 }
0131
0132 robust_fpt& operator-=(const robust_fpt& that) {
0133 floating_point_type fpv = this->fpv_ - that.fpv_;
0134 if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
0135 (!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
0136 this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
0137 } else {
0138 floating_point_type temp =
0139 (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
0140 if (is_neg(temp))
0141 temp = -temp;
0142 this->re_ = temp + ROUNDING_ERROR;
0143 }
0144 this->fpv_ = fpv;
0145 return *this;
0146 }
0147
0148 robust_fpt& operator*=(const robust_fpt& that) {
0149 this->re_ += that.re_ + ROUNDING_ERROR;
0150 this->fpv_ *= that.fpv_;
0151 return *this;
0152 }
0153
0154 robust_fpt& operator/=(const robust_fpt& that) {
0155 this->re_ += that.re_ + ROUNDING_ERROR;
0156 this->fpv_ /= that.fpv_;
0157 return *this;
0158 }
0159
0160 robust_fpt operator+(const robust_fpt& that) const {
0161 floating_point_type fpv = this->fpv_ + that.fpv_;
0162 relative_error_type re;
0163 if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
0164 (!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
0165 re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
0166 } else {
0167 floating_point_type temp =
0168 (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
0169 if (is_neg(temp))
0170 temp = -temp;
0171 re = temp + ROUNDING_ERROR;
0172 }
0173 return robust_fpt(fpv, re);
0174 }
0175
0176 robust_fpt operator-(const robust_fpt& that) const {
0177 floating_point_type fpv = this->fpv_ - that.fpv_;
0178 relative_error_type re;
0179 if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
0180 (!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
0181 re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
0182 } else {
0183 floating_point_type temp =
0184 (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
0185 if (is_neg(temp))
0186 temp = -temp;
0187 re = temp + ROUNDING_ERROR;
0188 }
0189 return robust_fpt(fpv, re);
0190 }
0191
0192 robust_fpt operator*(const robust_fpt& that) const {
0193 floating_point_type fpv = this->fpv_ * that.fpv_;
0194 relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
0195 return robust_fpt(fpv, re);
0196 }
0197
0198 robust_fpt operator/(const robust_fpt& that) const {
0199 floating_point_type fpv = this->fpv_ / that.fpv_;
0200 relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
0201 return robust_fpt(fpv, re);
0202 }
0203
0204 robust_fpt sqrt() const {
0205 return robust_fpt(get_sqrt(fpv_),
0206 re_ * static_cast<relative_error_type>(0.5) +
0207 ROUNDING_ERROR);
0208 }
0209
0210 private:
0211 floating_point_type fpv_;
0212 relative_error_type re_;
0213 };
0214
0215 template <typename T>
0216 robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
0217 return that.sqrt();
0218 }
0219
0220 template <typename T>
0221 bool is_pos(const robust_fpt<T>& that) {
0222 return that.has_pos_value();
0223 }
0224
0225 template <typename T>
0226 bool is_neg(const robust_fpt<T>& that) {
0227 return that.has_neg_value();
0228 }
0229
0230 template <typename T>
0231 bool is_zero(const robust_fpt<T>& that) {
0232 return that.has_zero_value();
0233 }
0234
0235
0236
0237
0238
0239
0240 template <typename T>
0241 class robust_dif {
0242 public:
0243 robust_dif() :
0244 positive_sum_(0),
0245 negative_sum_(0) {}
0246
0247 explicit robust_dif(const T& value) :
0248 positive_sum_((value > 0)?value:0),
0249 negative_sum_((value < 0)?-value:0) {}
0250
0251 robust_dif(const T& pos, const T& neg) :
0252 positive_sum_(pos),
0253 negative_sum_(neg) {}
0254
0255 T dif() const {
0256 return positive_sum_ - negative_sum_;
0257 }
0258
0259 T pos() const {
0260 return positive_sum_;
0261 }
0262
0263 T neg() const {
0264 return negative_sum_;
0265 }
0266
0267 robust_dif<T> operator-() const {
0268 return robust_dif(negative_sum_, positive_sum_);
0269 }
0270
0271 robust_dif<T>& operator+=(const T& val) {
0272 if (!is_neg(val))
0273 positive_sum_ += val;
0274 else
0275 negative_sum_ -= val;
0276 return *this;
0277 }
0278
0279 robust_dif<T>& operator+=(const robust_dif<T>& that) {
0280 positive_sum_ += that.positive_sum_;
0281 negative_sum_ += that.negative_sum_;
0282 return *this;
0283 }
0284
0285 robust_dif<T>& operator-=(const T& val) {
0286 if (!is_neg(val))
0287 negative_sum_ += val;
0288 else
0289 positive_sum_ -= val;
0290 return *this;
0291 }
0292
0293 robust_dif<T>& operator-=(const robust_dif<T>& that) {
0294 positive_sum_ += that.negative_sum_;
0295 negative_sum_ += that.positive_sum_;
0296 return *this;
0297 }
0298
0299 robust_dif<T>& operator*=(const T& val) {
0300 if (!is_neg(val)) {
0301 positive_sum_ *= val;
0302 negative_sum_ *= val;
0303 } else {
0304 positive_sum_ *= -val;
0305 negative_sum_ *= -val;
0306 swap();
0307 }
0308 return *this;
0309 }
0310
0311 robust_dif<T>& operator*=(const robust_dif<T>& that) {
0312 T positive_sum = this->positive_sum_ * that.positive_sum_ +
0313 this->negative_sum_ * that.negative_sum_;
0314 T negative_sum = this->positive_sum_ * that.negative_sum_ +
0315 this->negative_sum_ * that.positive_sum_;
0316 positive_sum_ = positive_sum;
0317 negative_sum_ = negative_sum;
0318 return *this;
0319 }
0320
0321 robust_dif<T>& operator/=(const T& val) {
0322 if (!is_neg(val)) {
0323 positive_sum_ /= val;
0324 negative_sum_ /= val;
0325 } else {
0326 positive_sum_ /= -val;
0327 negative_sum_ /= -val;
0328 swap();
0329 }
0330 return *this;
0331 }
0332
0333 private:
0334 void swap() {
0335 (std::swap)(positive_sum_, negative_sum_);
0336 }
0337
0338 T positive_sum_;
0339 T negative_sum_;
0340 };
0341
0342 template<typename T>
0343 robust_dif<T> operator+(const robust_dif<T>& lhs,
0344 const robust_dif<T>& rhs) {
0345 return robust_dif<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg());
0346 }
0347
0348 template<typename T>
0349 robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
0350 if (!is_neg(rhs)) {
0351 return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
0352 } else {
0353 return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
0354 }
0355 }
0356
0357 template<typename T>
0358 robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
0359 if (!is_neg(lhs)) {
0360 return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
0361 } else {
0362 return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
0363 }
0364 }
0365
0366 template<typename T>
0367 robust_dif<T> operator-(const robust_dif<T>& lhs,
0368 const robust_dif<T>& rhs) {
0369 return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
0370 }
0371
0372 template<typename T>
0373 robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
0374 if (!is_neg(rhs)) {
0375 return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
0376 } else {
0377 return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
0378 }
0379 }
0380
0381 template<typename T>
0382 robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
0383 if (!is_neg(lhs)) {
0384 return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
0385 } else {
0386 return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
0387 }
0388 }
0389
0390 template<typename T>
0391 robust_dif<T> operator*(const robust_dif<T>& lhs,
0392 const robust_dif<T>& rhs) {
0393 T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
0394 T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
0395 return robust_dif<T>(res_pos, res_neg);
0396 }
0397
0398 template<typename T>
0399 robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
0400 if (!is_neg(val)) {
0401 return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
0402 } else {
0403 return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
0404 }
0405 }
0406
0407 template<typename T>
0408 robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
0409 if (!is_neg(val)) {
0410 return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
0411 } else {
0412 return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
0413 }
0414 }
0415
0416 template<typename T>
0417 robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
0418 if (!is_neg(val)) {
0419 return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
0420 } else {
0421 return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
0422 }
0423 }
0424
0425
0426
0427
0428 template <typename _int, typename _fpt, typename _converter>
0429 class robust_sqrt_expr {
0430 public:
0431 enum MAX_RELATIVE_ERROR {
0432 MAX_RELATIVE_ERROR_EVAL1 = 4,
0433 MAX_RELATIVE_ERROR_EVAL2 = 7,
0434 MAX_RELATIVE_ERROR_EVAL3 = 16,
0435 MAX_RELATIVE_ERROR_EVAL4 = 25
0436 };
0437
0438
0439
0440 _fpt eval1(_int* A, _int* B) {
0441 _fpt a = convert(A[0]);
0442 _fpt b = convert(B[0]);
0443 return a * get_sqrt(b);
0444 }
0445
0446
0447
0448 _fpt eval2(_int* A, _int* B) {
0449 _fpt a = eval1(A, B);
0450 _fpt b = eval1(A + 1, B + 1);
0451 if ((!is_neg(a) && !is_neg(b)) ||
0452 (!is_pos(a) && !is_pos(b)))
0453 return a + b;
0454 return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
0455 }
0456
0457
0458
0459 _fpt eval3(_int* A, _int* B) {
0460 _fpt a = eval2(A, B);
0461 _fpt b = eval1(A + 2, B + 2);
0462 if ((!is_neg(a) && !is_neg(b)) ||
0463 (!is_pos(a) && !is_pos(b)))
0464 return a + b;
0465 tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
0466 tB[3] = 1;
0467 tA[4] = A[0] * A[1] * 2;
0468 tB[4] = B[0] * B[1];
0469 return eval2(tA + 3, tB + 3) / (a - b);
0470 }
0471
0472
0473
0474
0475
0476 _fpt eval4(_int* A, _int* B) {
0477 _fpt a = eval2(A, B);
0478 _fpt b = eval2(A + 2, B + 2);
0479 if ((!is_neg(a) && !is_neg(b)) ||
0480 (!is_pos(a) && !is_pos(b)))
0481 return a + b;
0482 tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
0483 A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
0484 tB[0] = 1;
0485 tA[1] = A[0] * A[1] * 2;
0486 tB[1] = B[0] * B[1];
0487 tA[2] = A[2] * A[3] * -2;
0488 tB[2] = B[2] * B[3];
0489 return eval3(tA, tB) / (a - b);
0490 }
0491
0492 private:
0493 _int tA[5];
0494 _int tB[5];
0495 _converter convert;
0496 };
0497 }
0498 }
0499 }
0500
0501 #endif