assign_scalar.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. #include <cmath>
  10. template <>
  11. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  12. const CGAL::Epeck::FT & rhs,
  13. const bool & slow_and_more_precise,
  14. double & lhs)
  15. {
  16. if(slow_and_more_precise)
  17. {
  18. return assign_scalar(rhs,lhs);
  19. }else
  20. {
  21. // While this is significantly faster (100x), this does not guarantee that
  22. // two equivalent rationals produce the same double (e.g.,
  23. // CGAL::to_double(⅓) ≠ CGAL::to_double(1-⅔))
  24. // https://github.com/CGAL/cgal/discussions/6000 For remesh_intersections,
  25. // `unique` is called _after_ rounding to floats, avoiding more expensive
  26. // rational equality tests. To operate correctly, we need that a=b ⇒
  27. // double(a)=double(b). Alternatively, we could require that
  28. // remesh_intersections conduct its `unique` operation on rationals. This is
  29. // even more expensive (4x) and most of the time probably overkill, though
  30. // it is argueably more correct in terms of producing the correct topology
  31. // (despite degeneracies that appear during rounding). On the other hand,
  32. // this rounding-before-unique only occurs if the requested output is float,
  33. // so its a question of combinatorial vs geometric degeneracies. Argueably,
  34. // combinatorial degeneracies are more reliably detected.
  35. //
  36. //lhs = CGAL::to_double(rhs);
  37. lhs = CGAL::to_double(rhs.exact());
  38. }
  39. }
  40. template <>
  41. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  42. const CGAL::Epeck::FT & rhs,
  43. const bool & slow_and_more_precise,
  44. float & lhs)
  45. {
  46. double d;
  47. igl::copyleft::cgal::assign_scalar(rhs,slow_and_more_precise,d);
  48. lhs = float(d);
  49. }
  50. // If we haven't specialized the types then `slow_and_more_precise` doesn't make sense.
  51. template <typename RHS, typename LHS>
  52. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  53. const RHS & rhs,
  54. const bool & /*slow_and_more_precise*/,
  55. LHS & lhs)
  56. {
  57. return assign_scalar(rhs,lhs);
  58. }
  59. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  60. const CGAL::Epeck::FT & cgal,
  61. CGAL::Epeck::FT & d)
  62. {
  63. d = cgal;
  64. }
  65. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  66. const CGAL::Epeck::FT & _cgal,
  67. double & d)
  68. {
  69. // FORCE evaluation of the exact type otherwise interval might be huge.
  70. const CGAL::Epeck::FT cgal = _cgal.exact();
  71. const auto interval = CGAL::to_interval(cgal);
  72. d = interval.first;
  73. do {
  74. const double next = std::nextafter(d, interval.second);
  75. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  76. d = next;
  77. } while (d < interval.second);
  78. }
  79. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  80. const CGAL::Epeck::FT & _cgal,
  81. float& d)
  82. {
  83. // FORCE evaluation of the exact type otherwise interval might be huge.
  84. const CGAL::Epeck::FT cgal = _cgal.exact();
  85. const auto interval = CGAL::to_interval(cgal);
  86. d = interval.first;
  87. do {
  88. const float next = std::nextafter(d, float(interval.second));
  89. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  90. d = next;
  91. } while (d < float(interval.second));
  92. }
  93. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  94. const double & c,
  95. double & d)
  96. {
  97. d = c;
  98. }
  99. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  100. const float& c,
  101. float& d)
  102. {
  103. d = c;
  104. }
  105. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  106. const float& c,
  107. double& d)
  108. {
  109. d = c;
  110. }
  111. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  112. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  113. CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & d)
  114. {
  115. d = cgal;
  116. }
  117. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  118. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  119. double & d)
  120. {
  121. const auto interval = CGAL::to_interval(cgal);
  122. d = interval.first;
  123. do {
  124. const double next = std::nextafter(d, interval.second);
  125. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  126. d = next;
  127. } while (d < interval.second);
  128. }
  129. IGL_INLINE void igl::copyleft::cgal::assign_scalar(
  130. const CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt::FT & cgal,
  131. float& d)
  132. {
  133. const auto interval = CGAL::to_interval(cgal);
  134. d = interval.first;
  135. do {
  136. const float next = std::nextafter(d, float(interval.second));
  137. if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
  138. d = next;
  139. } while (d < float(interval.second));
  140. }
  141. #ifdef IGL_STATIC_LIBRARY
  142. // Explicit template instantiation
  143. // generated by autoexplicit.sh
  144. template void igl::copyleft::cgal::assign_scalar<float, double>(float const&, bool const&, double&);
  145. // generated by autoexplicit.sh
  146. template void igl::copyleft::cgal::assign_scalar<float, CGAL::Epeck::FT >(float const&, bool const&, CGAL::Epeck::FT&);
  147. template void igl::copyleft::cgal::assign_scalar<double, double>(double const&, bool const&, double&);
  148. template void igl::copyleft::cgal::assign_scalar<double, CGAL::Epeck::FT >(double const&, bool const&, CGAL::Epeck::FT&);
  149. template void igl::copyleft::cgal::assign_scalar<CGAL::Epeck::FT, CGAL::Epeck::FT >(CGAL::Epeck::FT const&, bool const&, CGAL::Epeck::FT&);
  150. #endif