precise_math.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
  3. // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
  4. // Contributed and/or modified by Tinko Bartels,
  5. // as part of Google Summer of Code 2019 program.
  6. // This file was modified by Oracle on 2021.
  7. // Modifications copyright (c) 2021, Oracle and/or its affiliates.
  8. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
  9. // Use, modification and distribution is subject to the Boost Software License,
  10. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
  13. #define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
  14. #include<numeric>
  15. #include<cmath>
  16. #include<limits>
  17. #include<array>
  18. #include <boost/geometry/core/access.hpp>
  19. #include <boost/geometry/util/condition.hpp>
  20. // The following code is based on "Adaptive Precision Floating-Point Arithmetic
  21. // and Fast Robust Geometric Predicates" by Richard Shewchuk,
  22. // J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321
  23. namespace boost { namespace geometry
  24. {
  25. namespace detail { namespace precise_math
  26. {
  27. // See Theorem 6, page 6
  28. template
  29. <
  30. typename RealNumber
  31. >
  32. inline std::array<RealNumber, 2> fast_two_sum(RealNumber const a,
  33. RealNumber const b)
  34. {
  35. RealNumber x = a + b;
  36. RealNumber b_virtual = x - a;
  37. return {{x, b - b_virtual}};
  38. }
  39. // See Theorem 7, page 7 - 8
  40. template
  41. <
  42. typename RealNumber
  43. >
  44. inline std::array<RealNumber, 2> two_sum(RealNumber const a,
  45. RealNumber const b)
  46. {
  47. RealNumber x = a + b;
  48. RealNumber b_virtual = x - a;
  49. RealNumber a_virtual = x - b_virtual;
  50. RealNumber b_roundoff = b - b_virtual;
  51. RealNumber a_roundoff = a - a_virtual;
  52. RealNumber y = a_roundoff + b_roundoff;
  53. return {{ x, y }};
  54. }
  55. // See bottom of page 8
  56. template
  57. <
  58. typename RealNumber
  59. >
  60. inline RealNumber two_diff_tail(RealNumber const a,
  61. RealNumber const b,
  62. RealNumber const x)
  63. {
  64. RealNumber b_virtual = a - x;
  65. RealNumber a_virtual = x + b_virtual;
  66. RealNumber b_roundoff = b_virtual - b;
  67. RealNumber a_roundoff = a - a_virtual;
  68. return a_roundoff + b_roundoff;
  69. }
  70. // see bottom of page 8
  71. template
  72. <
  73. typename RealNumber
  74. >
  75. inline std::array<RealNumber, 2> two_diff(RealNumber const a,
  76. RealNumber const b)
  77. {
  78. RealNumber x = a - b;
  79. RealNumber y = two_diff_tail(a, b, x);
  80. return {{ x, y }};
  81. }
  82. // see theorem 18, page 19
  83. template
  84. <
  85. typename RealNumber
  86. >
  87. inline RealNumber two_product_tail(RealNumber const a,
  88. RealNumber const b,
  89. RealNumber const x)
  90. {
  91. return std::fma(a, b, -x);
  92. }
  93. // see theorem 18, page 19
  94. template
  95. <
  96. typename RealNumber
  97. >
  98. inline std::array<RealNumber, 2> two_product(RealNumber const a,
  99. RealNumber const b)
  100. {
  101. RealNumber x = a * b;
  102. RealNumber y = two_product_tail(a, b, x);
  103. return {{ x , y }};
  104. }
  105. // see theorem 12, figure 7, page 11 - 12,
  106. // this is the 2 by 2 case for the corresponding diff-method
  107. // note that this method takes input in descending order of magnitude and
  108. // returns components in ascending order of magnitude
  109. template
  110. <
  111. typename RealNumber
  112. >
  113. inline std::array<RealNumber, 4> two_two_expansion_diff(
  114. std::array<RealNumber, 2> const a,
  115. std::array<RealNumber, 2> const b)
  116. {
  117. std::array<RealNumber, 4> h;
  118. std::array<RealNumber, 2> Qh = two_diff(a[1], b[1]);
  119. h[0] = Qh[1];
  120. Qh = two_sum( a[0], Qh[0] );
  121. RealNumber _j = Qh[0];
  122. Qh = two_diff(Qh[1], b[0]);
  123. h[1] = Qh[1];
  124. Qh = two_sum( _j, Qh[0] );
  125. h[2] = Qh[1];
  126. h[3] = Qh[0];
  127. return h;
  128. }
  129. // see theorem 13, figure 8. This implementation uses zero elimination as
  130. // suggested on page 17, second to last paragraph. Returns the number of
  131. // non-zero components in the result and writes the result to h.
  132. // the merger into a single sequence g is done implicitly
  133. template
  134. <
  135. typename RealNumber,
  136. std::size_t InSize1,
  137. std::size_t InSize2,
  138. std::size_t OutSize
  139. >
  140. inline int fast_expansion_sum_zeroelim(
  141. std::array<RealNumber, InSize1> const& e,
  142. std::array<RealNumber, InSize2> const& f,
  143. std::array<RealNumber, OutSize> & h,
  144. int m = InSize1,
  145. int n = InSize2)
  146. {
  147. std::array<RealNumber, 2> Qh;
  148. int i_e = 0;
  149. int i_f = 0;
  150. int i_h = 0;
  151. if (std::abs(f[0]) > std::abs(e[0]))
  152. {
  153. Qh[0] = e[i_e++];
  154. }
  155. else
  156. {
  157. Qh[0] = f[i_f++];
  158. }
  159. i_h = 0;
  160. if ((i_e < m) && (i_f < n))
  161. {
  162. if (std::abs(f[i_f]) > std::abs(e[i_e]))
  163. {
  164. Qh = fast_two_sum(e[i_e++], Qh[0]);
  165. }
  166. else
  167. {
  168. Qh = fast_two_sum(f[i_f++], Qh[0]);
  169. }
  170. if (Qh[1] != 0.0)
  171. {
  172. h[i_h++] = Qh[1];
  173. }
  174. while ((i_e < m) && (i_f < n))
  175. {
  176. if (std::abs(f[i_f]) > std::abs(e[i_e]))
  177. {
  178. Qh = two_sum(Qh[0], e[i_e++]);
  179. }
  180. else
  181. {
  182. Qh = two_sum(Qh[0], f[i_f++]);
  183. }
  184. if (Qh[1] != 0.0)
  185. {
  186. h[i_h++] = Qh[1];
  187. }
  188. }
  189. }
  190. while (i_e < m)
  191. {
  192. Qh = two_sum(Qh[0], e[i_e++]);
  193. if (Qh[1] != 0.0)
  194. {
  195. h[i_h++] = Qh[1];
  196. }
  197. }
  198. while (i_f < n)
  199. {
  200. Qh = two_sum(Qh[0], f[i_f++]);
  201. if (Qh[1] != 0.0)
  202. {
  203. h[i_h++] = Qh[1];
  204. }
  205. }
  206. if ((Qh[0] != 0.0) || (i_h == 0))
  207. {
  208. h[i_h++] = Qh[0];
  209. }
  210. return i_h;
  211. }
  212. // see theorem 19, figure 13, page 20 - 21. This implementation uses zero
  213. // elimination as suggested on page 17, second to last paragraph. Returns the
  214. // number of non-zero components in the result and writes the result to h.
  215. template
  216. <
  217. typename RealNumber,
  218. std::size_t InSize
  219. >
  220. inline int scale_expansion_zeroelim(
  221. std::array<RealNumber, InSize> const& e,
  222. RealNumber const b,
  223. std::array<RealNumber, 2 * InSize> & h,
  224. int e_non_zeros = InSize)
  225. {
  226. std::array<RealNumber, 2> Qh = two_product(e[0], b);
  227. int i_h = 0;
  228. if (Qh[1] != 0)
  229. {
  230. h[i_h++] = Qh[1];
  231. }
  232. for (int i_e = 1; i_e < e_non_zeros; i_e++)
  233. {
  234. std::array<RealNumber, 2> Tt = two_product(e[i_e], b);
  235. Qh = two_sum(Qh[0], Tt[1]);
  236. if (Qh[1] != 0)
  237. {
  238. h[i_h++] = Qh[1];
  239. }
  240. Qh = fast_two_sum(Tt[0], Qh[0]);
  241. if (Qh[1] != 0)
  242. {
  243. h[i_h++] = Qh[1];
  244. }
  245. }
  246. if ((Qh[0] != 0.0) || (i_h == 0))
  247. {
  248. h[i_h++] = Qh[0];
  249. }
  250. return i_h;
  251. }
  252. template<typename RealNumber>
  253. struct vec2d
  254. {
  255. RealNumber x;
  256. RealNumber y;
  257. };
  258. template
  259. <
  260. typename RealNumber,
  261. std::size_t Robustness
  262. >
  263. inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
  264. vec2d<RealNumber> const& p2,
  265. vec2d<RealNumber> const& p3,
  266. std::array<RealNumber, 2>& t1,
  267. std::array<RealNumber, 2>& t2,
  268. std::array<RealNumber, 2>& t3,
  269. std::array<RealNumber, 2>& t4,
  270. std::array<RealNumber, 2>& t5_01,
  271. std::array<RealNumber, 2>& t6_01,
  272. RealNumber const& magnitude)
  273. {
  274. t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]);
  275. t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]);
  276. std::array<RealNumber, 4> tA_03 = two_two_expansion_diff(t5_01, t6_01);
  277. RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast<RealNumber>(0));
  278. if (BOOST_GEOMETRY_CONDITION(Robustness == 1))
  279. {
  280. return det;
  281. }
  282. // see p.39, mind the different definition of epsilon for error bound
  283. RealNumber B_relative_bound =
  284. (1 + 3 * std::numeric_limits<RealNumber>::epsilon())
  285. * std::numeric_limits<RealNumber>::epsilon();
  286. RealNumber absolute_bound = B_relative_bound * magnitude;
  287. if (std::abs(det) >= absolute_bound)
  288. {
  289. return det; //B estimate
  290. }
  291. t1[1] = two_diff_tail(p1.x, p3.x, t1[0]);
  292. t2[1] = two_diff_tail(p2.y, p3.y, t2[0]);
  293. t3[1] = two_diff_tail(p1.y, p3.y, t3[0]);
  294. t4[1] = two_diff_tail(p2.x, p3.x, t4[0]);
  295. if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0))
  296. {
  297. return det; //If all tails are zero, there is noething else to compute
  298. }
  299. RealNumber sub_bound =
  300. (1.5 + 2 * std::numeric_limits<RealNumber>::epsilon())
  301. * std::numeric_limits<RealNumber>::epsilon();
  302. // see p.39, mind the different definition of epsilon for error bound
  303. RealNumber C_relative_bound =
  304. (2.25 + 8 * std::numeric_limits<RealNumber>::epsilon())
  305. * std::numeric_limits<RealNumber>::epsilon()
  306. * std::numeric_limits<RealNumber>::epsilon();
  307. absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
  308. det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]);
  309. if (BOOST_GEOMETRY_CONDITION(Robustness == 2) || std::abs(det) >= absolute_bound)
  310. {
  311. return det; //C estimate
  312. }
  313. std::array<RealNumber, 8> D_left;
  314. int D_left_nz;
  315. {
  316. std::array<RealNumber, 2> t5_23 = two_product(t1[1], t2[0]);
  317. std::array<RealNumber, 2> t6_23 = two_product(t3[1], t4[0]);
  318. std::array<RealNumber, 4> tA_47 = two_two_expansion_diff(t5_23, t6_23);
  319. D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left);
  320. }
  321. std::array<RealNumber, 8> D_right;
  322. int D_right_nz;
  323. {
  324. std::array<RealNumber, 2> t5_45 = two_product(t1[0], t2[1]);
  325. std::array<RealNumber, 2> t6_45 = two_product(t3[0], t4[1]);
  326. std::array<RealNumber, 4> tA_8_11 = two_two_expansion_diff(t5_45, t6_45);
  327. std::array<RealNumber, 2> t5_67 = two_product(t1[1], t2[1]);
  328. std::array<RealNumber, 2> t6_67 = two_product(t3[1], t4[1]);
  329. std::array<RealNumber, 4> tA_12_15 = two_two_expansion_diff(t5_67, t6_67);
  330. D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right);
  331. }
  332. std::array<RealNumber, 16> D;
  333. int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz);
  334. // only return component of highest magnitude because we mostly care about the sign.
  335. return(D[D_nz - 1]);
  336. }
  337. // see page 38, Figure 21 for the calculations, notation follows the notation
  338. // in the figure.
  339. template
  340. <
  341. typename RealNumber,
  342. std::size_t Robustness = 3,
  343. typename EpsPolicy
  344. >
  345. inline RealNumber orient2d(vec2d<RealNumber> const& p1,
  346. vec2d<RealNumber> const& p2,
  347. vec2d<RealNumber> const& p3,
  348. EpsPolicy& eps_policy)
  349. {
  350. std::array<RealNumber, 2> t1, t2, t3, t4;
  351. t1[0] = p1.x - p3.x;
  352. t2[0] = p2.y - p3.y;
  353. t3[0] = p1.y - p3.y;
  354. t4[0] = p2.x - p3.x;
  355. eps_policy = EpsPolicy(t1[0], t2[0], t3[0], t4[0]);
  356. std::array<RealNumber, 2> t5_01, t6_01;
  357. t5_01[0] = t1[0] * t2[0];
  358. t6_01[0] = t3[0] * t4[0];
  359. RealNumber det = t5_01[0] - t6_01[0];
  360. if (BOOST_GEOMETRY_CONDITION(Robustness == 0))
  361. {
  362. return det;
  363. }
  364. RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]);
  365. // see p.39, mind the different definition of epsilon for error bound
  366. RealNumber const A_relative_bound =
  367. (1.5 + 4 * std::numeric_limits<RealNumber>::epsilon())
  368. * std::numeric_limits<RealNumber>::epsilon();
  369. RealNumber absolute_bound = A_relative_bound * magnitude;
  370. if ( std::abs(det) >= absolute_bound )
  371. {
  372. return det; //A estimate
  373. }
  374. if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) )
  375. {
  376. //if diagonal and antidiagonal have different sign, the sign of det is
  377. //obvious
  378. return det;
  379. }
  380. return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4,
  381. t5_01, t6_01, magnitude);
  382. }
  383. // This method adaptively computes increasingly precise approximations of the following
  384. // determinant using Laplace expansion along the last column.
  385. // det A =
  386. // | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
  387. // | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
  388. // | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 |
  389. // = a_13 * C_13 + a_23 * C_23 + a_33 * C_33
  390. // where a_ij is the i-j-entry and C_ij is the i_j Cofactor
  391. template
  392. <
  393. typename RealNumber,
  394. std::size_t Robustness = 2
  395. >
  396. RealNumber incircle(std::array<RealNumber, 2> const& p1,
  397. std::array<RealNumber, 2> const& p2,
  398. std::array<RealNumber, 2> const& p3,
  399. std::array<RealNumber, 2> const& p4)
  400. {
  401. RealNumber A_11 = p1[0] - p4[0];
  402. RealNumber A_21 = p2[0] - p4[0];
  403. RealNumber A_31 = p3[0] - p4[0];
  404. RealNumber A_12 = p1[1] - p4[1];
  405. RealNumber A_22 = p2[1] - p4[1];
  406. RealNumber A_32 = p3[1] - p4[1];
  407. std::array<RealNumber, 2> A_21_x_A_32,
  408. A_31_x_A_22,
  409. A_31_x_A_12,
  410. A_11_x_A_32,
  411. A_11_x_A_22,
  412. A_21_x_A_12;
  413. A_21_x_A_32[0] = A_21 * A_32;
  414. A_31_x_A_22[0] = A_31 * A_22;
  415. RealNumber A_13 = A_11 * A_11 + A_12 * A_12;
  416. A_31_x_A_12[0] = A_31 * A_12;
  417. A_11_x_A_32[0] = A_11 * A_32;
  418. RealNumber A_23 = A_21 * A_21 + A_22 * A_22;
  419. A_11_x_A_22[0] = A_11 * A_22;
  420. A_21_x_A_12[0] = A_21 * A_12;
  421. RealNumber A_33 = A_31 * A_31 + A_32 * A_32;
  422. RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0])
  423. + A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0])
  424. + A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]);
  425. if (BOOST_GEOMETRY_CONDITION(Robustness == 0))
  426. {
  427. return det;
  428. }
  429. RealNumber magnitude =
  430. (std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13
  431. + (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23
  432. + (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33;
  433. RealNumber A_relative_bound =
  434. (5 + 24 * std::numeric_limits<RealNumber>::epsilon())
  435. * std::numeric_limits<RealNumber>::epsilon();
  436. RealNumber absolute_bound = A_relative_bound * magnitude;
  437. if (std::abs(det) > absolute_bound)
  438. {
  439. return det;
  440. }
  441. // (p2_x - p4_x) * (p3_y - p4_y)
  442. A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]);
  443. // (p3_x - p4_x) * (p2_y - p4_y)
  444. A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]);
  445. // (bx - dx) * (cy - dy) - (cx - dx) * (by - dy)
  446. std::array<RealNumber, 4> C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22);
  447. std::array<RealNumber, 8> C_13_x_A11;
  448. // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx )
  449. int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11);
  450. std::array<RealNumber, 16> C_13_x_A11_sq;
  451. // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx)
  452. int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11,
  453. A_11,
  454. C_13_x_A11_sq,
  455. C_13_x_A11_nz);
  456. std::array<RealNumber, 8> C_13_x_A12;
  457. // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy )
  458. int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12);
  459. std::array<RealNumber, 16> C_13_x_A12_sq;
  460. // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy )
  461. int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12,
  462. C_13_x_A12_sq,
  463. C_13_x_A12_nz);
  464. std::array<RealNumber, 32> A_13_x_C13;
  465. // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) )
  466. // * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) )
  467. int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq,
  468. C_13_x_A12_sq,
  469. A_13_x_C13,
  470. C_13_x_A11_sq_nz,
  471. C_13_x_A12_sq_nz);
  472. // (cx - dx) * (ay - dy)
  473. A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]);
  474. // (ax - dx) * (cy - dy)
  475. A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]);
  476. // (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy)
  477. std::array<RealNumber, 4> C_23 = two_two_expansion_diff(A_31_x_A_12,
  478. A_11_x_A_32);
  479. std::array<RealNumber, 8> C_23_x_A_21;
  480. // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx )
  481. int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21);
  482. std::array<RealNumber, 16> C_23_x_A_21_sq;
  483. // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx )
  484. int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21,
  485. C_23_x_A_21_sq,
  486. C_23_x_A_21_nz);
  487. std::array<RealNumber, 8> C_23_x_A_22;
  488. // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy )
  489. int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22);
  490. std::array<RealNumber, 16> C_23_x_A_22_sq;
  491. // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy )
  492. int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22,
  493. C_23_x_A_22_sq,
  494. C_23_x_A_22_nz);
  495. std::array<RealNumber, 32> A_23_x_C_23;
  496. // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) )
  497. // * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) )
  498. int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq,
  499. C_23_x_A_22_sq,
  500. A_23_x_C_23,
  501. C_23_x_A_21_sq_nz,
  502. C_23_x_A_22_sq_nz);
  503. // (ax - dx) * (by - dy)
  504. A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]);
  505. // (bx - dx) * (ay - dy)
  506. A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]);
  507. // (ax - dx) * (by - dy) - (bx - dx) * (ay - dy)
  508. std::array<RealNumber, 4> C_33 = two_two_expansion_diff(A_11_x_A_22,
  509. A_21_x_A_12);
  510. std::array<RealNumber, 8> C_33_x_A31;
  511. // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx )
  512. int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31);
  513. std::array<RealNumber, 16> C_33_x_A31_sq;
  514. // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx )
  515. int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31,
  516. C_33_x_A31_sq,
  517. C_33_x_A31_nz);
  518. std::array<RealNumber, 8> C_33_x_A_32;
  519. // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy )
  520. int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32);
  521. std::array<RealNumber, 16> C_33_x_A_32_sq;
  522. // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy )
  523. int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32,
  524. C_33_x_A_32_sq,
  525. C_33_x_A_32_nz);
  526. std::array<RealNumber, 32> A_33_x_C_33;
  527. int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq,
  528. C_33_x_A_32_sq,
  529. A_33_x_C_33,
  530. C_33_x_A31_sq_nz,
  531. C_33_x_A_32_sq_nz);
  532. std::array<RealNumber, 64> A_13_x_C13_p_A_13_x_C13;
  533. int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim(
  534. A_13_x_C13, A_23_x_C_23,
  535. A_13_x_C13_p_A_13_x_C13,
  536. A_13_x_C13_nz,
  537. A_23_x_C_23_nz);
  538. std::array<RealNumber, 96> det_expansion;
  539. int det_expansion_nz = fast_expansion_sum_zeroelim(
  540. A_13_x_C13_p_A_13_x_C13,
  541. A_33_x_C_33,
  542. det_expansion,
  543. A_13_x_C13_p_A_13_x_C13_nz,
  544. A_33_x_C_33_nz);
  545. det = std::accumulate(det_expansion.begin(),
  546. det_expansion.begin() + det_expansion_nz,
  547. static_cast<RealNumber>(0));
  548. if (BOOST_GEOMETRY_CONDITION(Robustness == 1))
  549. {
  550. return det;
  551. }
  552. RealNumber B_relative_bound =
  553. (2 + 12 * std::numeric_limits<RealNumber>::epsilon())
  554. * std::numeric_limits<RealNumber>::epsilon();
  555. absolute_bound = B_relative_bound * magnitude;
  556. if (std::abs(det) >= absolute_bound)
  557. {
  558. return det;
  559. }
  560. RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11);
  561. RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12);
  562. RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21);
  563. RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22);
  564. RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31);
  565. RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32);
  566. if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0)
  567. && (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0))
  568. {
  569. return det;
  570. }
  571. // RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits<RealNumber>::epsilon())
  572. // * std::numeric_limits<RealNumber>::epsilon();
  573. // RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits<RealNumber>::epsilon())
  574. // * std::numeric_limits<RealNumber>::epsilon()
  575. // * std::numeric_limits<RealNumber>::epsilon();
  576. //absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
  577. det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail)
  578. - (A_22 * A_31tail + A_31 * A_22tail))
  579. + 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31))
  580. + ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail)
  581. - (A_32 * A_11tail + A_11 * A_32tail))
  582. + 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11))
  583. + ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail)
  584. - (A_12 * A_21tail + A_21 * A_12tail))
  585. + 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21));
  586. //if (std::abs(det) >= absolute_bound)
  587. //{
  588. return det;
  589. //}
  590. }
  591. }} // namespace detail::precise_math
  592. }} // namespace boost::geometry
  593. #endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP