2
0

assign_scalar.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "assign_scalar.h"
  9. template <>
  10. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  11. const CGAL::Epeck::FT & rhs,
  12. const bool & slow_and_more_precise,
  13. double & lhs)
  14. {
  15. if(slow_and_more_precise)
  16. {
  17. return assign_scalar(rhs,lhs);
  18. }else
  19. {
  20. // While this is significantly faster (100x), this does not guarantee that
  21. // two equivalent rationals produce the same double (e.g.,
  22. // CGAL::to_double(⅓) ≠ CGAL::to_double(1-⅔))
  23. // https://github.com/CGAL/cgal/discussions/6000 For remesh_intersections,
  24. // `unique` is called _after_ rounding to floats, avoiding more expensive
  25. // rational equality tests. To operate correctly, we need that a=b ⇒
  26. // double(a)=double(b). Alternatively, we could require that
  27. // remesh_intersections conduct its `unique` operation on rationals. This is
  28. // even more expensive (4x) and most of the time probably overkill, though
  29. // it is argueably more correct in terms of producing the correct topology
  30. // (despite degeneracies that appear during rounding). On the other hand,
  31. // this rounding-before-unique only occurs if the requested output is float,
  32. // so its a question of combinatorial vs geometric degeneracies. Argueably,
  33. // combinatorial degeneracies are more reliably detected.
  34. //
  35. //lhs = CGAL::to_double(rhs);
  36. lhs = CGAL::to_double(rhs.exact());
  37. }
  38. }
  39. template <>
  40. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  41. const CGAL::Epeck::FT & rhs,
  42. const bool & slow_and_more_precise,
  43. float & lhs)
  44. {
  45. double d;
  46. igl::copyleft::cgal::assign_scalar(rhs,slow_and_more_precise,d);
  47. lhs = float(d);
  48. }
  49. // If we haven't specialized the types then `slow_and_more_precise` doesn't make sense.
  50. template <typename RHS, typename LHS>
  51. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  52. const RHS & rhs,
  53. const bool & /*slow_and_more_precise*/,
  54. LHS & lhs)
  55. {
  56. return assign_scalar(rhs,lhs);
  57. }
  58. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  59. const CGAL::Epeck::FT & cgal,
  60. CGAL::Epeck::FT & d)
  61. {
  62. d = cgal;
  63. }
  64. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  65. const CGAL::Epeck::FT & _cgal,
  66. double & d)
  67. {
  68. // FORCE evaluation of the exact type otherwise interval might be huge.
  69. const CGAL::Epeck::FT cgal = _cgal.exact();
  70. const auto interval = CGAL::to_interval(cgal);
  71. d = interval.first;
  72. do {
  73. const double next = nextafter(d, interval.second);
  74. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  75. d = next;
  76. } while (d < interval.second);
  77. }
  78. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  79. const CGAL::Epeck::FT & _cgal,
  80. float& d)
  81. {
  82. // FORCE evaluation of the exact type otherwise interval might be huge.
  83. const CGAL::Epeck::FT cgal = _cgal.exact();
  84. const auto interval = CGAL::to_interval(cgal);
  85. d = interval.first;
  86. do {
  87. const float next = nextafter(d, float(interval.second));
  88. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  89. d = next;
  90. } while (d < float(interval.second));
  91. }
  92. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  93. const double & c,
  94. double & d)
  95. {
  96. d = c;
  97. }
  98. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  99. const float& c,
  100. float& d)
  101. {
  102. d = c;
  103. }
  104. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  105. const float& c,
  106. double& d)
  107. {
  108. d = c;
  109. }
  110. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  111. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  112. CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & d)
  113. {
  114. d = cgal;
  115. }
  116. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  117. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  118. double & d)
  119. {
  120. const auto interval = CGAL::to_interval(cgal);
  121. d = interval.first;
  122. do {
  123. const double next = nextafter(d, interval.second);
  124. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  125. d = next;
  126. } while (d < interval.second);
  127. }
  128. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  129. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  130. float& d)
  131. {
  132. const auto interval = CGAL::to_interval(cgal);
  133. d = interval.first;
  134. do {
  135. const float next = nextafter(d, float(interval.second));
  136. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  137. d = next;
  138. } while (d < float(interval.second));
  139. }
  140. #ifndef WIN32
  141. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  142. const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
  143. CGAL::Simple_cartesian<mpq_class>::FT & d)
  144. {
  145. d = cgal;
  146. }
  147. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  148. const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
  149. double & d)
  150. {
  151. const auto interval = CGAL::to_interval(cgal);
  152. d = interval.first;
  153. do {
  154. const double next = nextafter(d, interval.second);
  155. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  156. d = next;
  157. } while (d < interval.second);
  158. }
  159. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  160. const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
  161. float& d)
  162. {
  163. const auto interval = CGAL::to_interval(cgal);
  164. d = interval.first;
  165. do {
  166. const float next = nextafter(d, float(interval.second));
  167. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  168. d = next;
  169. } while (d < float(interval.second));
  170. }
  171. #endif // WIN32
  172. #ifdef IGL_STATIC_LIBRARY
  173. // Explicit template instantiation
  174. // generated by autoexplicit.sh
  175. template void igl::copyleft::cgal::assign_scalar<float, double>(float const&, bool const&, double&);
  176. // generated by autoexplicit.sh
  177. template void igl::copyleft::cgal::assign_scalar<float, CGAL::Epeck::FT >(float const&, bool const&, CGAL::Epeck::FT&);
  178. template void igl::copyleft::cgal::assign_scalar<double, double>(double const&, bool const&, double&);
  179. template void igl::copyleft::cgal::assign_scalar<double, CGAL::Epeck::FT >(double const&, bool const&, CGAL::Epeck::FT&);
  180. template void igl::copyleft::cgal::assign_scalar<CGAL::Epeck::FT, CGAL::Epeck::FT >(CGAL::Epeck::FT const&, bool const&, CGAL::Epeck::FT&);
  181. #endif