RootsBisection.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <functional>
  9. // Compute a root of a function F(t) on an interval [t0, t1]. The caller
  10. // specifies the maximum number of iterations, in case you want limited
  11. // accuracy for the root. However, the function is designed for native types
  12. // (Real = float/double). If you specify a sufficiently large number of
  13. // iterations, the root finder bisects until either F(t) is identically zero
  14. // [a condition dependent on how you structure F(t) for evaluation] or the
  15. // midpoint (t0 + t1)/2 rounds numerically to tmin or tmax. Of course, it
  16. // is required that t0 < t1. The return value of Find is:
  17. // 0: F(t0)*F(t1) > 0, we cannot determine a root
  18. // 1: F(t0) = 0 or F(t1) = 0
  19. // 2..maxIterations: the number of bisections plus one
  20. // maxIterations+1: the loop executed without a break (no convergence)
  21. namespace WwiseGTE
  22. {
  23. template <typename Real>
  24. class RootsBisection
  25. {
  26. public:
  27. // Use this function when F(t0) and F(t1) are not already known.
  28. static unsigned int Find(std::function<Real(Real)> const& F, Real t0,
  29. Real t1, unsigned int maxIterations, Real& root)
  30. {
  31. // Set 'root' initially to avoid "potentially uninitialized
  32. // variable" warnings by a compiler.
  33. root = t0;
  34. if (t0 < t1)
  35. {
  36. // Test the endpoints to see whether F(t) is zero.
  37. Real f0 = F(t0);
  38. if (f0 == (Real)0)
  39. {
  40. root = t0;
  41. return 1;
  42. }
  43. Real f1 = F(t1);
  44. if (f1 == (Real)0)
  45. {
  46. root = t1;
  47. return 1;
  48. }
  49. if (f0 * f1 > (Real)0)
  50. {
  51. // It is not known whether the interval bounds a root.
  52. return 0;
  53. }
  54. unsigned int i;
  55. for (i = 2; i <= maxIterations; ++i)
  56. {
  57. root = (Real)0.5 * (t0 + t1);
  58. if (root == t0 || root == t1)
  59. {
  60. // The numbers t0 and t1 are consecutive
  61. // floating-point numbers.
  62. break;
  63. }
  64. Real fm = F(root);
  65. Real product = fm * f0;
  66. if (product < (Real)0)
  67. {
  68. t1 = root;
  69. f1 = fm;
  70. }
  71. else if (product > (Real)0)
  72. {
  73. t0 = root;
  74. f0 = fm;
  75. }
  76. else
  77. {
  78. break;
  79. }
  80. }
  81. return i;
  82. }
  83. else
  84. {
  85. // The interval endpoints are invalid.
  86. return 0;
  87. }
  88. }
  89. // If f0 = F(t0) and f1 = F(t1) are already known, pass them to the
  90. // bisector. This is useful when |f0| or |f1| is infinite, and you
  91. // can pass sign(f0) or sign(f1) rather than then infinity because
  92. // the bisector cares only about the signs of f.
  93. static unsigned int Find(std::function<Real(Real)> const& F, Real t0,
  94. Real t1, Real f0, Real f1, unsigned int maxIterations, Real& root)
  95. {
  96. // Set 'root' initially to avoid "potentially uninitialized
  97. // variable" warnings by a compiler.
  98. root = t0;
  99. if (t0 < t1)
  100. {
  101. // Test the endpoints to see whether F(t) is zero.
  102. if (f0 == (Real)0)
  103. {
  104. root = t0;
  105. return 1;
  106. }
  107. if (f1 == (Real)0)
  108. {
  109. root = t1;
  110. return 1;
  111. }
  112. if (f0 * f1 > (Real)0)
  113. {
  114. // It is not known whether the interval bounds a root.
  115. return 0;
  116. }
  117. unsigned int i;
  118. root = t0;
  119. for (i = 2; i <= maxIterations; ++i)
  120. {
  121. root = (Real)0.5 * (t0 + t1);
  122. if (root == t0 || root == t1)
  123. {
  124. // The numbers t0 and t1 are consecutive
  125. // floating-point numbers.
  126. break;
  127. }
  128. Real fm = F(root);
  129. Real product = fm * f0;
  130. if (product < (Real)0)
  131. {
  132. t1 = root;
  133. f1 = fm;
  134. }
  135. else if (product > (Real)0)
  136. {
  137. t0 = root;
  138. f0 = fm;
  139. }
  140. else
  141. {
  142. break;
  143. }
  144. }
  145. return i;
  146. }
  147. else
  148. {
  149. // The interval endpoints are invalid.
  150. return 0;
  151. }
  152. }
  153. };
  154. }