voronoi_ctypes.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // Boost.Polygon library detail/voronoi_ctypes.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_CTYPES
  8. #define BOOST_POLYGON_DETAIL_VORONOI_CTYPES
  9. #include <boost/cstdint.hpp>
  10. #include <algorithm>
  11. #include <cmath>
  12. #include <cstring>
  13. #include <utility>
  14. #include <vector>
  15. namespace boost {
  16. namespace polygon {
  17. namespace detail {
  18. typedef boost::int32_t int32;
  19. typedef boost::int64_t int64;
  20. typedef boost::uint32_t uint32;
  21. typedef boost::uint64_t uint64;
  22. typedef double fpt64;
  23. // If two floating-point numbers in the same format are ordered (x < y),
  24. // then they are ordered the same way when their bits are reinterpreted as
  25. // sign-magnitude integers. Values are considered to be almost equal if
  26. // their integer bits reinterpretations differ in not more than maxUlps units.
  27. template <typename _fpt>
  28. struct ulp_comparison;
  29. template <>
  30. struct ulp_comparison<fpt64> {
  31. enum Result {
  32. LESS = -1,
  33. EQUAL = 0,
  34. MORE = 1
  35. };
  36. Result operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const {
  37. uint64 ll_a, ll_b;
  38. // Reinterpret double bits as 64-bit signed integer.
  39. std::memcpy(&ll_a, &a, sizeof(fpt64));
  40. std::memcpy(&ll_b, &b, sizeof(fpt64));
  41. // Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000.
  42. // Map negative zero to an integer zero representation - making it
  43. // identical to positive zero - the smallest negative number is
  44. // represented by negative one, and downwards from there.
  45. if (ll_a < 0x8000000000000000ULL)
  46. ll_a = 0x8000000000000000ULL - ll_a;
  47. if (ll_b < 0x8000000000000000ULL)
  48. ll_b = 0x8000000000000000ULL - ll_b;
  49. // Compare 64-bit signed integer representations of input values.
  50. // Difference in 1 Ulp is equivalent to a relative error of between
  51. // 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
  52. if (ll_a > ll_b)
  53. return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS;
  54. return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE;
  55. }
  56. };
  57. template <typename _fpt>
  58. struct extened_exponent_fpt_traits;
  59. template <>
  60. struct extened_exponent_fpt_traits<fpt64> {
  61. public:
  62. typedef int exp_type;
  63. enum {
  64. MAX_SIGNIFICANT_EXP_DIF = 54
  65. };
  66. };
  67. // Floating point type wrapper. Allows to extend exponent boundaries to the
  68. // integer type range. This class does not handle division by zero, subnormal
  69. // numbers or NaNs.
  70. template <typename _fpt, typename _traits = extened_exponent_fpt_traits<_fpt> >
  71. class extended_exponent_fpt {
  72. public:
  73. typedef _fpt fpt_type;
  74. typedef typename _traits::exp_type exp_type;
  75. explicit extended_exponent_fpt(fpt_type val) {
  76. val_ = std::frexp(val, &exp_);
  77. }
  78. extended_exponent_fpt(fpt_type val, exp_type exp) {
  79. val_ = std::frexp(val, &exp_);
  80. exp_ += exp;
  81. }
  82. bool is_pos() const {
  83. return val_ > 0;
  84. }
  85. bool is_neg() const {
  86. return val_ < 0;
  87. }
  88. bool is_zero() const {
  89. return val_ == 0;
  90. }
  91. extended_exponent_fpt operator-() const {
  92. return extended_exponent_fpt(-val_, exp_);
  93. }
  94. extended_exponent_fpt operator+(const extended_exponent_fpt& that) const {
  95. if (this->val_ == 0.0 ||
  96. that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
  97. return that;
  98. }
  99. if (that.val_ == 0.0 ||
  100. this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
  101. return *this;
  102. }
  103. if (this->exp_ >= that.exp_) {
  104. exp_type exp_dif = this->exp_ - that.exp_;
  105. fpt_type val = std::ldexp(this->val_, exp_dif) + that.val_;
  106. return extended_exponent_fpt(val, that.exp_);
  107. } else {
  108. exp_type exp_dif = that.exp_ - this->exp_;
  109. fpt_type val = std::ldexp(that.val_, exp_dif) + this->val_;
  110. return extended_exponent_fpt(val, this->exp_);
  111. }
  112. }
  113. extended_exponent_fpt operator-(const extended_exponent_fpt& that) const {
  114. if (this->val_ == 0.0 ||
  115. that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
  116. return extended_exponent_fpt(-that.val_, that.exp_);
  117. }
  118. if (that.val_ == 0.0 ||
  119. this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
  120. return *this;
  121. }
  122. if (this->exp_ >= that.exp_) {
  123. exp_type exp_dif = this->exp_ - that.exp_;
  124. fpt_type val = std::ldexp(this->val_, exp_dif) - that.val_;
  125. return extended_exponent_fpt(val, that.exp_);
  126. } else {
  127. exp_type exp_dif = that.exp_ - this->exp_;
  128. fpt_type val = std::ldexp(-that.val_, exp_dif) + this->val_;
  129. return extended_exponent_fpt(val, this->exp_);
  130. }
  131. }
  132. extended_exponent_fpt operator*(const extended_exponent_fpt& that) const {
  133. fpt_type val = this->val_ * that.val_;
  134. exp_type exp = this->exp_ + that.exp_;
  135. return extended_exponent_fpt(val, exp);
  136. }
  137. extended_exponent_fpt operator/(const extended_exponent_fpt& that) const {
  138. fpt_type val = this->val_ / that.val_;
  139. exp_type exp = this->exp_ - that.exp_;
  140. return extended_exponent_fpt(val, exp);
  141. }
  142. extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) {
  143. return *this = *this + that;
  144. }
  145. extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) {
  146. return *this = *this - that;
  147. }
  148. extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) {
  149. return *this = *this * that;
  150. }
  151. extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) {
  152. return *this = *this / that;
  153. }
  154. extended_exponent_fpt sqrt() const {
  155. fpt_type val = val_;
  156. exp_type exp = exp_;
  157. if (exp & 1) {
  158. val *= 2.0;
  159. --exp;
  160. }
  161. return extended_exponent_fpt(std::sqrt(val), exp >> 1);
  162. }
  163. fpt_type d() const {
  164. return std::ldexp(val_, exp_);
  165. }
  166. private:
  167. fpt_type val_;
  168. exp_type exp_;
  169. };
  170. typedef extended_exponent_fpt<double> efpt64;
  171. template <typename _fpt>
  172. extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) {
  173. return that.sqrt();
  174. }
  175. template <typename _fpt>
  176. bool is_pos(const extended_exponent_fpt<_fpt>& that) {
  177. return that.is_pos();
  178. }
  179. template <typename _fpt>
  180. bool is_neg(const extended_exponent_fpt<_fpt>& that) {
  181. return that.is_neg();
  182. }
  183. template <typename _fpt>
  184. bool is_zero(const extended_exponent_fpt<_fpt>& that) {
  185. return that.is_zero();
  186. }
  187. // Very efficient stack allocated big integer class.
  188. // Supports next set of arithmetic operations: +, -, *.
  189. template<std::size_t N>
  190. class extended_int {
  191. public:
  192. extended_int() {}
  193. extended_int(int32 that) {
  194. if (that > 0) {
  195. this->chunks_[0] = that;
  196. this->count_ = 1;
  197. } else if (that < 0) {
  198. this->chunks_[0] = -that;
  199. this->count_ = -1;
  200. } else {
  201. this->count_ = 0;
  202. }
  203. }
  204. extended_int(int64 that) {
  205. if (that > 0) {
  206. this->chunks_[0] = static_cast<uint32>(that);
  207. this->chunks_[1] = that >> 32;
  208. this->count_ = this->chunks_[1] ? 2 : 1;
  209. } else if (that < 0) {
  210. that = -that;
  211. this->chunks_[0] = static_cast<uint32>(that);
  212. this->chunks_[1] = that >> 32;
  213. this->count_ = this->chunks_[1] ? -2 : -1;
  214. } else {
  215. this->count_ = 0;
  216. }
  217. }
  218. extended_int(const std::vector<uint32>& chunks, bool plus = true) {
  219. this->count_ = static_cast<int32>((std::min)(N, chunks.size()));
  220. for (int i = 0; i < this->count_; ++i)
  221. this->chunks_[i] = chunks[chunks.size() - i - 1];
  222. if (!plus)
  223. this->count_ = -this->count_;
  224. }
  225. template<std::size_t M>
  226. extended_int(const extended_int<M>& that) {
  227. this->count_ = that.count();
  228. std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
  229. }
  230. extended_int& operator=(int32 that) {
  231. if (that > 0) {
  232. this->chunks_[0] = that;
  233. this->count_ = 1;
  234. } else if (that < 0) {
  235. this->chunks_[0] = -that;
  236. this->count_ = -1;
  237. } else {
  238. this->count_ = 0;
  239. }
  240. return *this;
  241. }
  242. extended_int& operator=(int64 that) {
  243. if (that > 0) {
  244. this->chunks_[0] = static_cast<uint32>(that);
  245. this->chunks_[1] = that >> 32;
  246. this->count_ = this->chunks_[1] ? 2 : 1;
  247. } else if (that < 0) {
  248. that = -that;
  249. this->chunks_[0] = static_cast<uint32>(that);
  250. this->chunks_[1] = that >> 32;
  251. this->count_ = this->chunks_[1] ? -2 : -1;
  252. } else {
  253. this->count_ = 0;
  254. }
  255. return *this;
  256. }
  257. template<std::size_t M>
  258. extended_int& operator=(const extended_int<M>& that) {
  259. this->count_ = that.count();
  260. std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
  261. return *this;
  262. }
  263. bool is_pos() const {
  264. return this->count_ > 0;
  265. }
  266. bool is_neg() const {
  267. return this->count_ < 0;
  268. }
  269. bool is_zero() const {
  270. return this->count_ == 0;
  271. }
  272. bool operator==(const extended_int& that) const {
  273. if (this->count_ != that.count())
  274. return false;
  275. for (std::size_t i = 0; i < this->size(); ++i)
  276. if (this->chunks_[i] != that.chunks()[i])
  277. return false;
  278. return true;
  279. }
  280. bool operator!=(const extended_int& that) const {
  281. return !(*this == that);
  282. }
  283. bool operator<(const extended_int& that) const {
  284. if (this->count_ != that.count())
  285. return this->count_ < that.count();
  286. std::size_t i = this->size();
  287. if (!i)
  288. return false;
  289. do {
  290. --i;
  291. if (this->chunks_[i] != that.chunks()[i])
  292. return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0);
  293. } while (i);
  294. return false;
  295. }
  296. bool operator>(const extended_int& that) const {
  297. return that < *this;
  298. }
  299. bool operator<=(const extended_int& that) const {
  300. return !(that < *this);
  301. }
  302. bool operator>=(const extended_int& that) const {
  303. return !(*this < that);
  304. }
  305. extended_int operator-() const {
  306. extended_int ret_val = *this;
  307. ret_val.neg();
  308. return ret_val;
  309. }
  310. void neg() {
  311. this->count_ = -this->count_;
  312. }
  313. extended_int operator+(const extended_int& that) const {
  314. extended_int ret_val;
  315. ret_val.add(*this, that);
  316. return ret_val;
  317. }
  318. void add(const extended_int& e1, const extended_int& e2) {
  319. if (!e1.count()) {
  320. *this = e2;
  321. return;
  322. }
  323. if (!e2.count()) {
  324. *this = e1;
  325. return;
  326. }
  327. if ((e1.count() > 0) ^ (e2.count() > 0)) {
  328. dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
  329. } else {
  330. add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
  331. }
  332. if (e1.count() < 0)
  333. this->count_ = -this->count_;
  334. }
  335. extended_int operator-(const extended_int& that) const {
  336. extended_int ret_val;
  337. ret_val.dif(*this, that);
  338. return ret_val;
  339. }
  340. void dif(const extended_int& e1, const extended_int& e2) {
  341. if (!e1.count()) {
  342. *this = e2;
  343. this->count_ = -this->count_;
  344. return;
  345. }
  346. if (!e2.count()) {
  347. *this = e1;
  348. return;
  349. }
  350. if ((e1.count() > 0) ^ (e2.count() > 0)) {
  351. add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
  352. } else {
  353. dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
  354. }
  355. if (e1.count() < 0)
  356. this->count_ = -this->count_;
  357. }
  358. extended_int operator*(int32 that) const {
  359. extended_int temp(that);
  360. return (*this) * temp;
  361. }
  362. extended_int operator*(int64 that) const {
  363. extended_int temp(that);
  364. return (*this) * temp;
  365. }
  366. extended_int operator*(const extended_int& that) const {
  367. extended_int ret_val;
  368. ret_val.mul(*this, that);
  369. return ret_val;
  370. }
  371. void mul(const extended_int& e1, const extended_int& e2) {
  372. if (!e1.count() || !e2.count()) {
  373. this->count_ = 0;
  374. return;
  375. }
  376. mul(e1.chunks(), e1.size(), e2.chunks(), e2.size());
  377. if ((e1.count() > 0) ^ (e2.count() > 0))
  378. this->count_ = -this->count_;
  379. }
  380. const uint32* chunks() const {
  381. return chunks_;
  382. }
  383. int32 count() const {
  384. return count_;
  385. }
  386. std::size_t size() const {
  387. return (std::abs)(count_);
  388. }
  389. std::pair<fpt64, int> p() const {
  390. std::pair<fpt64, int> ret_val(0, 0);
  391. std::size_t sz = this->size();
  392. if (!sz) {
  393. return ret_val;
  394. } else {
  395. if (sz == 1) {
  396. ret_val.first = static_cast<fpt64>(this->chunks_[0]);
  397. } else if (sz == 2) {
  398. ret_val.first = static_cast<fpt64>(this->chunks_[1]) *
  399. static_cast<fpt64>(0x100000000LL) +
  400. static_cast<fpt64>(this->chunks_[0]);
  401. } else {
  402. for (std::size_t i = 1; i <= 3; ++i) {
  403. ret_val.first *= static_cast<fpt64>(0x100000000LL);
  404. ret_val.first += static_cast<fpt64>(this->chunks_[sz - i]);
  405. }
  406. ret_val.second = static_cast<int>((sz - 3) << 5);
  407. }
  408. }
  409. if (this->count_ < 0)
  410. ret_val.first = -ret_val.first;
  411. return ret_val;
  412. }
  413. fpt64 d() const {
  414. std::pair<fpt64, int> p = this->p();
  415. return std::ldexp(p.first, p.second);
  416. }
  417. private:
  418. void add(const uint32* c1, std::size_t sz1,
  419. const uint32* c2, std::size_t sz2) {
  420. if (sz1 < sz2) {
  421. add(c2, sz2, c1, sz1);
  422. return;
  423. }
  424. this->count_ = static_cast<int32>(sz1);
  425. uint64 temp = 0;
  426. for (std::size_t i = 0; i < sz2; ++i) {
  427. temp += static_cast<uint64>(c1[i]) + static_cast<uint64>(c2[i]);
  428. this->chunks_[i] = static_cast<uint32>(temp);
  429. temp >>= 32;
  430. }
  431. for (std::size_t i = sz2; i < sz1; ++i) {
  432. temp += static_cast<uint64>(c1[i]);
  433. this->chunks_[i] = static_cast<uint32>(temp);
  434. temp >>= 32;
  435. }
  436. if (temp && (this->count_ != N)) {
  437. this->chunks_[this->count_] = static_cast<uint32>(temp);
  438. ++this->count_;
  439. }
  440. }
  441. void dif(const uint32* c1, std::size_t sz1,
  442. const uint32* c2, std::size_t sz2,
  443. bool rec = false) {
  444. if (sz1 < sz2) {
  445. dif(c2, sz2, c1, sz1, true);
  446. this->count_ = -this->count_;
  447. return;
  448. } else if ((sz1 == sz2) && !rec) {
  449. do {
  450. --sz1;
  451. if (c1[sz1] < c2[sz1]) {
  452. ++sz1;
  453. dif(c2, sz1, c1, sz1, true);
  454. this->count_ = -this->count_;
  455. return;
  456. } else if (c1[sz1] > c2[sz1]) {
  457. ++sz1;
  458. break;
  459. }
  460. } while (sz1);
  461. if (!sz1) {
  462. this->count_ = 0;
  463. return;
  464. }
  465. sz2 = sz1;
  466. }
  467. this->count_ = static_cast<int32>(sz1-1);
  468. bool flag = false;
  469. for (std::size_t i = 0; i < sz2; ++i) {
  470. this->chunks_[i] = c1[i] - c2[i] - (flag?1:0);
  471. flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag);
  472. }
  473. for (std::size_t i = sz2; i < sz1; ++i) {
  474. this->chunks_[i] = c1[i] - (flag?1:0);
  475. flag = !c1[i] && flag;
  476. }
  477. if (this->chunks_[this->count_])
  478. ++this->count_;
  479. }
  480. void mul(const uint32* c1, std::size_t sz1,
  481. const uint32* c2, std::size_t sz2) {
  482. uint64 cur = 0, nxt, tmp;
  483. this->count_ = static_cast<int32>((std::min)(N, sz1 + sz2 - 1));
  484. for (std::size_t shift = 0; shift < static_cast<std::size_t>(this->count_);
  485. ++shift) {
  486. nxt = 0;
  487. for (std::size_t first = 0; first <= shift; ++first) {
  488. if (first >= sz1)
  489. break;
  490. std::size_t second = shift - first;
  491. if (second >= sz2)
  492. continue;
  493. tmp = static_cast<uint64>(c1[first]) * static_cast<uint64>(c2[second]);
  494. cur += static_cast<uint32>(tmp);
  495. nxt += tmp >> 32;
  496. }
  497. this->chunks_[shift] = static_cast<uint32>(cur);
  498. cur = nxt + (cur >> 32);
  499. }
  500. if (cur && (this->count_ != N)) {
  501. this->chunks_[this->count_] = static_cast<uint32>(cur);
  502. ++this->count_;
  503. }
  504. }
  505. uint32 chunks_[N];
  506. int32 count_;
  507. };
  508. template <std::size_t N>
  509. bool is_pos(const extended_int<N>& that) {
  510. return that.count() > 0;
  511. }
  512. template <std::size_t N>
  513. bool is_neg(const extended_int<N>& that) {
  514. return that.count() < 0;
  515. }
  516. template <std::size_t N>
  517. bool is_zero(const extended_int<N>& that) {
  518. return !that.count();
  519. }
  520. struct type_converter_fpt {
  521. template <typename T>
  522. fpt64 operator()(const T& that) const {
  523. return static_cast<fpt64>(that);
  524. }
  525. template <std::size_t N>
  526. fpt64 operator()(const extended_int<N>& that) const {
  527. return that.d();
  528. }
  529. fpt64 operator()(const extended_exponent_fpt<fpt64>& that) const {
  530. return that.d();
  531. }
  532. };
  533. struct type_converter_efpt {
  534. template <std::size_t N>
  535. extended_exponent_fpt<fpt64> operator()(const extended_int<N>& that) const {
  536. std::pair<fpt64, int> p = that.p();
  537. return extended_exponent_fpt<fpt64>(p.first, p.second);
  538. }
  539. };
  540. // Voronoi coordinate type traits make it possible to extend algorithm
  541. // input coordinate range to any user provided integer type and algorithm
  542. // output coordinate range to any ieee-754 like floating point type.
  543. template <typename T>
  544. struct voronoi_ctype_traits;
  545. template <>
  546. struct voronoi_ctype_traits<int32> {
  547. typedef int32 int_type;
  548. typedef int64 int_x2_type;
  549. typedef uint64 uint_x2_type;
  550. typedef extended_int<64> big_int_type;
  551. typedef fpt64 fpt_type;
  552. typedef extended_exponent_fpt<fpt_type> efpt_type;
  553. typedef ulp_comparison<fpt_type> ulp_cmp_type;
  554. typedef type_converter_fpt to_fpt_converter_type;
  555. typedef type_converter_efpt to_efpt_converter_type;
  556. };
  557. } // detail
  558. } // polygon
  559. } // boost
  560. #endif // BOOST_POLYGON_DETAIL_VORONOI_CTYPES