RootsPolynomial.h 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  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.12.05
  7. #pragma once
  8. #include <Mathematics/Math.h>
  9. #include <algorithm>
  10. #include <map>
  11. #include <vector>
  12. // The Find functions return the number of roots, if any, and this number
  13. // of elements of the outputs are valid. If the polynomial is identically
  14. // zero, Find returns 1.
  15. //
  16. // Some root-bounding algorithms for real-valued roots are mentioned next for
  17. // the polynomial p(t) = c[0] + c[1]*t + ... + c[d-1]*t^{d-1} + c[d]*t^d.
  18. //
  19. // 1. The roots must be contained by the interval [-M,M] where
  20. // M = 1 + max{|c[0]|, ..., |c[d-1]|}/|c[d]| >= 1
  21. // is called the Cauchy bound.
  22. //
  23. // 2. You may search for roots in the interval [-1,1]. Define
  24. // q(t) = t^d*p(1/t) = c[0]*t^d + c[1]*t^{d-1} + ... + c[d-1]*t + c[d]
  25. // The roots of p(t) not in [-1,1] are the roots of q(t) in [-1,1].
  26. //
  27. // 3. Between two consecutive roots of the derivative p'(t), say, r0 < r1,
  28. // the function p(t) is strictly monotonic on the open interval (r0,r1).
  29. // If additionally, p(r0) * p(r1) <= 0, then p(x) has a unique root on
  30. // the closed interval [r0,r1]. Thus, one can compute the derivatives
  31. // through order d for p(t), find roots for the derivative of order k+1,
  32. // then use these to bound roots for the derivative of order k.
  33. //
  34. // 4. Sturm sequences of polynomials may be used to determine bounds on the
  35. // roots. This is a more sophisticated approach to root bounding than item 3.
  36. // Moreover, a Sturm sequence allows you to compute the number of real-valued
  37. // roots on a specified interval.
  38. //
  39. // 5. For the low-degree Solve* functions, see
  40. // https://www.geometrictools.com/Documentation/LowDegreePolynomialRoots.pdf
  41. // FOR INTERNAL USE ONLY (unit testing). Do not define the symbol
  42. // GTE_ROOTS_LOW_DEGREE_UNIT_TEST in your own code.
  43. #if defined(GTE_ROOTS_LOW_DEGREE_UNIT_TEST)
  44. extern void RootsLowDegreeBlock(int);
  45. #define GTE_ROOTS_LOW_DEGREE_BLOCK(block) RootsLowDegreeBlock(block)
  46. #else
  47. #define GTE_ROOTS_LOW_DEGREE_BLOCK(block)
  48. #endif
  49. namespace WwiseGTE
  50. {
  51. template <typename Real>
  52. class RootsPolynomial
  53. {
  54. public:
  55. // Low-degree root finders. These use exact rational arithmetic for
  56. // theoretically correct root classification. The roots themselves
  57. // are computed with mixed types (rational and floating-point
  58. // arithmetic). The Rational type must support rational arithmetic
  59. // (+, -, *, /); for example, BSRational<UIntegerAP32> suffices. The
  60. // Rational class must have single-input constructors where the input
  61. // is type Real. This ensures you can call the Solve* functions with
  62. // floating-point inputs; they will be converted to Rational
  63. // implicitly. The highest-order coefficients must be nonzero
  64. // (p2 != 0 for quadratic, p3 != 0 for cubic, and p4 != 0 for
  65. // quartic).
  66. template <typename Rational>
  67. static void SolveQuadratic(Rational const& p0, Rational const& p1,
  68. Rational const& p2, std::map<Real, int>& rmMap)
  69. {
  70. Rational const rat2 = 2;
  71. Rational q0 = p0 / p2;
  72. Rational q1 = p1 / p2;
  73. Rational q1half = q1 / rat2;
  74. Rational c0 = q0 - q1half * q1half;
  75. std::map<Rational, int> rmLocalMap;
  76. SolveDepressedQuadratic(c0, rmLocalMap);
  77. rmMap.clear();
  78. for (auto& rm : rmLocalMap)
  79. {
  80. Rational root = rm.first - q1half;
  81. rmMap.insert(std::make_pair((Real)root, rm.second));
  82. }
  83. }
  84. template <typename Rational>
  85. static void SolveCubic(Rational const& p0, Rational const& p1,
  86. Rational const& p2, Rational const& p3, std::map<Real, int>& rmMap)
  87. {
  88. Rational const rat2 = 2, rat3 = 3;
  89. Rational q0 = p0 / p3;
  90. Rational q1 = p1 / p3;
  91. Rational q2 = p2 / p3;
  92. Rational q2third = q2 / rat3;
  93. Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
  94. Rational c1 = q1 - q2 * q2third;
  95. std::map<Rational, int> rmLocalMap;
  96. SolveDepressedCubic(c0, c1, rmLocalMap);
  97. rmMap.clear();
  98. for (auto& rm : rmLocalMap)
  99. {
  100. Rational root = rm.first - q2third;
  101. rmMap.insert(std::make_pair((Real)root, rm.second));
  102. }
  103. }
  104. template <typename Rational>
  105. static void SolveQuartic(Rational const& p0, Rational const& p1,
  106. Rational const& p2, Rational const& p3, Rational const& p4,
  107. std::map<Real, int>& rmMap)
  108. {
  109. Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
  110. Rational q0 = p0 / p4;
  111. Rational q1 = p1 / p4;
  112. Rational q2 = p2 / p4;
  113. Rational q3 = p3 / p4;
  114. Rational q3fourth = q3 / rat4;
  115. Rational q3fourthSqr = q3fourth * q3fourth;
  116. Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
  117. Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
  118. Rational c2 = q2 - rat6 * q3fourthSqr;
  119. std::map<Rational, int> rmLocalMap;
  120. SolveDepressedQuartic(c0, c1, c2, rmLocalMap);
  121. rmMap.clear();
  122. for (auto& rm : rmLocalMap)
  123. {
  124. Rational root = rm.first - q3fourth;
  125. rmMap.insert(std::make_pair((Real)root, rm.second));
  126. }
  127. }
  128. // Return only the number of real-valued roots and their
  129. // multiplicities. info.size() is the number of real-valued roots
  130. // and info[i] is the multiplicity of root corresponding to index i.
  131. template <typename Rational>
  132. static void GetRootInfoQuadratic(Rational const& p0, Rational const& p1,
  133. Rational const& p2, std::vector<int>& info)
  134. {
  135. Rational const rat2 = 2;
  136. Rational q0 = p0 / p2;
  137. Rational q1 = p1 / p2;
  138. Rational q1half = q1 / rat2;
  139. Rational c0 = q0 - q1half * q1half;
  140. info.clear();
  141. info.reserve(2);
  142. GetRootInfoDepressedQuadratic(c0, info);
  143. }
  144. template <typename Rational>
  145. static void GetRootInfoCubic(Rational const& p0, Rational const& p1,
  146. Rational const& p2, Rational const& p3, std::vector<int>& info)
  147. {
  148. Rational const rat2 = 2, rat3 = 3;
  149. Rational q0 = p0 / p3;
  150. Rational q1 = p1 / p3;
  151. Rational q2 = p2 / p3;
  152. Rational q2third = q2 / rat3;
  153. Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
  154. Rational c1 = q1 - q2 * q2third;
  155. info.clear();
  156. info.reserve(3);
  157. GetRootInfoDepressedCubic(c0, c1, info);
  158. }
  159. template <typename Rational>
  160. static void GetRootInfoQuartic(Rational const& p0, Rational const& p1,
  161. Rational const& p2, Rational const& p3, Rational const& p4,
  162. std::vector<int>& info)
  163. {
  164. Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
  165. Rational q0 = p0 / p4;
  166. Rational q1 = p1 / p4;
  167. Rational q2 = p2 / p4;
  168. Rational q3 = p3 / p4;
  169. Rational q3fourth = q3 / rat4;
  170. Rational q3fourthSqr = q3fourth * q3fourth;
  171. Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
  172. Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
  173. Rational c2 = q2 - rat6 * q3fourthSqr;
  174. info.clear();
  175. info.reserve(4);
  176. GetRootInfoDepressedQuartic(c0, c1, c2, info);
  177. }
  178. // General equations: sum_{i=0}^{d} c(i)*t^i = 0. The input array 'c'
  179. // must have at least d+1 elements and the output array 'root' must
  180. // have at least d elements.
  181. // Find the roots on (-infinity,+infinity).
  182. static int Find(int degree, Real const* c, unsigned int maxIterations, Real* roots)
  183. {
  184. if (degree >= 0 && c)
  185. {
  186. Real const zero = (Real)0;
  187. while (degree >= 0 && c[degree] == zero)
  188. {
  189. --degree;
  190. }
  191. if (degree > 0)
  192. {
  193. // Compute the Cauchy bound.
  194. Real const one = (Real)1;
  195. Real invLeading = one / c[degree];
  196. Real maxValue = zero;
  197. for (int i = 0; i < degree; ++i)
  198. {
  199. Real value = std::fabs(c[i] * invLeading);
  200. if (value > maxValue)
  201. {
  202. maxValue = value;
  203. }
  204. }
  205. Real bound = one + maxValue;
  206. return FindRecursive(degree, c, -bound, bound, maxIterations,
  207. roots);
  208. }
  209. else if (degree == 0)
  210. {
  211. // The polynomial is a nonzero constant.
  212. return 0;
  213. }
  214. else
  215. {
  216. // The polynomial is identically zero.
  217. roots[0] = zero;
  218. return 1;
  219. }
  220. }
  221. else
  222. {
  223. // Invalid degree or c.
  224. return 0;
  225. }
  226. }
  227. // If you know that p(tmin) * p(tmax) <= 0, then there must be at
  228. // least one root in [tmin, tmax]. Compute it using bisection.
  229. static bool Find(int degree, Real const* c, Real tmin, Real tmax,
  230. unsigned int maxIterations, Real& root)
  231. {
  232. Real const zero = (Real)0;
  233. Real pmin = Evaluate(degree, c, tmin);
  234. if (pmin == zero)
  235. {
  236. root = tmin;
  237. return true;
  238. }
  239. Real pmax = Evaluate(degree, c, tmax);
  240. if (pmax == zero)
  241. {
  242. root = tmax;
  243. return true;
  244. }
  245. if (pmin * pmax > zero)
  246. {
  247. // It is not known whether the interval bounds a root.
  248. return false;
  249. }
  250. if (tmin >= tmax)
  251. {
  252. // Invalid ordering of interval endpoitns.
  253. return false;
  254. }
  255. for (unsigned int i = 1; i <= maxIterations; ++i)
  256. {
  257. root = ((Real)0.5) * (tmin + tmax);
  258. // This test is designed for 'float' or 'double' when tmin
  259. // and tmax are consecutive floating-point numbers.
  260. if (root == tmin || root == tmax)
  261. {
  262. break;
  263. }
  264. Real p = Evaluate(degree, c, root);
  265. Real product = p * pmin;
  266. if (product < zero)
  267. {
  268. tmax = root;
  269. pmax = p;
  270. }
  271. else if (product > zero)
  272. {
  273. tmin = root;
  274. pmin = p;
  275. }
  276. else
  277. {
  278. break;
  279. }
  280. }
  281. return true;
  282. }
  283. private:
  284. // Support for the Solve* functions.
  285. template <typename Rational>
  286. static void SolveDepressedQuadratic(Rational const& c0,
  287. std::map<Rational, int>& rmMap)
  288. {
  289. Rational const zero = 0;
  290. if (c0 < zero)
  291. {
  292. // Two simple roots.
  293. Rational root1 = (Rational)std::sqrt((double)-c0);
  294. Rational root0 = -root1;
  295. rmMap.insert(std::make_pair(root0, 1));
  296. rmMap.insert(std::make_pair(root1, 1));
  297. GTE_ROOTS_LOW_DEGREE_BLOCK(0);
  298. }
  299. else if (c0 == zero)
  300. {
  301. // One double root.
  302. rmMap.insert(std::make_pair(zero, 2));
  303. GTE_ROOTS_LOW_DEGREE_BLOCK(1);
  304. }
  305. else // c0 > 0
  306. {
  307. // A complex-conjugate pair of roots.
  308. // Complex z0 = -q1/2 - i*sqrt(c0);
  309. // Complex z0conj = -q1/2 + i*sqrt(c0);
  310. GTE_ROOTS_LOW_DEGREE_BLOCK(2);
  311. }
  312. }
  313. template <typename Rational>
  314. static void SolveDepressedCubic(Rational const& c0, Rational const& c1,
  315. std::map<Rational, int>& rmMap)
  316. {
  317. // Handle the special case of c0 = 0, in which case the polynomial
  318. // reduces to a depressed quadratic.
  319. Rational const zero = 0;
  320. if (c0 == zero)
  321. {
  322. SolveDepressedQuadratic(c1, rmMap);
  323. auto iter = rmMap.find(zero);
  324. if (iter != rmMap.end())
  325. {
  326. // The quadratic has a root of zero, so the multiplicity
  327. // must be increased.
  328. ++iter->second;
  329. GTE_ROOTS_LOW_DEGREE_BLOCK(3);
  330. }
  331. else
  332. {
  333. // The quadratic does not have a root of zero. Insert the
  334. // one for the cubic.
  335. rmMap.insert(std::make_pair(zero, 1));
  336. GTE_ROOTS_LOW_DEGREE_BLOCK(4);
  337. }
  338. return;
  339. }
  340. // Handle the special case of c0 != 0 and c1 = 0.
  341. double const oneThird = 1.0 / 3.0;
  342. if (c1 == zero)
  343. {
  344. // One simple real root.
  345. Rational root0;
  346. if (c0 > zero)
  347. {
  348. root0 = (Rational)-std::pow((double)c0, oneThird);
  349. GTE_ROOTS_LOW_DEGREE_BLOCK(5);
  350. }
  351. else
  352. {
  353. root0 = (Rational)std::pow(-(double)c0, oneThird);
  354. GTE_ROOTS_LOW_DEGREE_BLOCK(6);
  355. }
  356. rmMap.insert(std::make_pair(root0, 1));
  357. // One complex conjugate pair.
  358. // Complex z0 = root0*(-1 - i*sqrt(3))/2;
  359. // Complex z0conj = root0*(-1 + i*sqrt(3))/2;
  360. return;
  361. }
  362. // At this time, c0 != 0 and c1 != 0.
  363. Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat27 = 27, rat108 = 108;
  364. Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
  365. if (delta > zero)
  366. {
  367. // Three simple roots.
  368. Rational deltaDiv108 = delta / rat108;
  369. Rational betaRe = -c0 / rat2;
  370. Rational betaIm = std::sqrt(deltaDiv108);
  371. Rational theta = std::atan2(betaIm, betaRe);
  372. Rational thetaDiv3 = theta / rat3;
  373. double angle = (double)thetaDiv3;
  374. Rational cs = (Rational)std::cos(angle);
  375. Rational sn = (Rational)std::sin(angle);
  376. Rational rhoSqr = betaRe * betaRe + betaIm * betaIm;
  377. Rational rhoPowThird = (Rational)std::pow((double)rhoSqr, 1.0 / 6.0);
  378. Rational temp0 = rhoPowThird * cs;
  379. Rational temp1 = rhoPowThird * sn * (Rational)std::sqrt(3.0);
  380. Rational root0 = rat2 * temp0;
  381. Rational root1 = -temp0 - temp1;
  382. Rational root2 = -temp0 + temp1;
  383. rmMap.insert(std::make_pair(root0, 1));
  384. rmMap.insert(std::make_pair(root1, 1));
  385. rmMap.insert(std::make_pair(root2, 1));
  386. GTE_ROOTS_LOW_DEGREE_BLOCK(7);
  387. }
  388. else if (delta < zero)
  389. {
  390. // One simple root.
  391. Rational deltaDiv108 = delta / rat108;
  392. Rational temp0 = -c0 / rat2;
  393. Rational temp1 = (Rational)std::sqrt(-(double)deltaDiv108);
  394. Rational temp2 = temp0 - temp1;
  395. Rational temp3 = temp0 + temp1;
  396. if (temp2 >= zero)
  397. {
  398. temp2 = (Rational)std::pow((double)temp2, oneThird);
  399. GTE_ROOTS_LOW_DEGREE_BLOCK(8);
  400. }
  401. else
  402. {
  403. temp2 = (Rational)-std::pow(-(double)temp2, oneThird);
  404. GTE_ROOTS_LOW_DEGREE_BLOCK(9);
  405. }
  406. if (temp3 >= zero)
  407. {
  408. temp3 = (Rational)std::pow((double)temp3, oneThird);
  409. GTE_ROOTS_LOW_DEGREE_BLOCK(10);
  410. }
  411. else
  412. {
  413. temp3 = (Rational)-std::pow(-(double)temp3, oneThird);
  414. GTE_ROOTS_LOW_DEGREE_BLOCK(11);
  415. }
  416. Rational root0 = temp2 + temp3;
  417. rmMap.insert(std::make_pair(root0, 1));
  418. // One complex conjugate pair.
  419. // Complex z0 = (-root0 - i*sqrt(3*root0*root0+4*c1))/2;
  420. // Complex z0conj = (-root0 + i*sqrt(3*root0*root0+4*c1))/2;
  421. }
  422. else // delta = 0
  423. {
  424. // One simple root and one double root.
  425. Rational root0 = -rat3 * c0 / (rat2 * c1);
  426. Rational root1 = -rat2 * root0;
  427. rmMap.insert(std::make_pair(root0, 2));
  428. rmMap.insert(std::make_pair(root1, 1));
  429. GTE_ROOTS_LOW_DEGREE_BLOCK(12);
  430. }
  431. }
  432. template <typename Rational>
  433. static void SolveDepressedQuartic(Rational const& c0, Rational const& c1,
  434. Rational const& c2, std::map<Rational, int>& rmMap)
  435. {
  436. // Handle the special case of c0 = 0, in which case the polynomial
  437. // reduces to a depressed cubic.
  438. Rational const zero = 0;
  439. if (c0 == zero)
  440. {
  441. SolveDepressedCubic(c1, c2, rmMap);
  442. auto iter = rmMap.find(zero);
  443. if (iter != rmMap.end())
  444. {
  445. // The cubic has a root of zero, so the multiplicity must
  446. // be increased.
  447. ++iter->second;
  448. GTE_ROOTS_LOW_DEGREE_BLOCK(13);
  449. }
  450. else
  451. {
  452. // The cubic does not have a root of zero. Insert the one
  453. // for the quartic.
  454. rmMap.insert(std::make_pair(zero, 1));
  455. GTE_ROOTS_LOW_DEGREE_BLOCK(14);
  456. }
  457. return;
  458. }
  459. // Handle the special case of c1 = 0, in which case the quartic is
  460. // a biquadratic
  461. // x^4 + c1*x^2 + c0 = (x^2 + c2/2)^2 + (c0 - c2^2/4)
  462. if (c1 == zero)
  463. {
  464. SolveBiquadratic(c0, c2, rmMap);
  465. return;
  466. }
  467. // At this time, c0 != 0 and c1 != 0, which is a requirement for
  468. // the general solver that must use a root of a special cubic
  469. // polynomial.
  470. Rational const rat2 = 2, rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
  471. Rational const rat27 = 27, rat36 = 36;
  472. Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
  473. Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
  474. (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
  475. rat16 * c0sqr);
  476. Rational a0 = rat12 * c0 + c2sqr;
  477. Rational a1 = rat4 * c0 - c2sqr;
  478. if (delta > zero)
  479. {
  480. if (c2 < zero && a1 < zero)
  481. {
  482. // Four simple real roots.
  483. std::map<Real, int> rmCubicMap;
  484. SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8, rmCubicMap);
  485. Rational t = (Rational)rmCubicMap.rbegin()->first;
  486. Rational alphaSqr = rat2 * t - c2;
  487. Rational alpha = (Rational)std::sqrt((double)alphaSqr);
  488. double sgnC1;
  489. if (c1 > zero)
  490. {
  491. sgnC1 = 1.0;
  492. GTE_ROOTS_LOW_DEGREE_BLOCK(15);
  493. }
  494. else
  495. {
  496. sgnC1 = -1.0;
  497. GTE_ROOTS_LOW_DEGREE_BLOCK(16);
  498. }
  499. Rational arg = t * t - c0;
  500. Rational beta = (Rational)(sgnC1 * std::sqrt(std::max((double)arg, 0.0)));
  501. Rational D0 = alphaSqr - rat4 * (t + beta);
  502. Rational sqrtD0 = (Rational)std::sqrt(std::max((double)D0, 0.0));
  503. Rational D1 = alphaSqr - rat4 * (t - beta);
  504. Rational sqrtD1 = (Rational)std::sqrt(std::max((double)D1, 0.0));
  505. Rational root0 = (alpha - sqrtD0) / rat2;
  506. Rational root1 = (alpha + sqrtD0) / rat2;
  507. Rational root2 = (-alpha - sqrtD1) / rat2;
  508. Rational root3 = (-alpha + sqrtD1) / rat2;
  509. rmMap.insert(std::make_pair(root0, 1));
  510. rmMap.insert(std::make_pair(root1, 1));
  511. rmMap.insert(std::make_pair(root2, 1));
  512. rmMap.insert(std::make_pair(root3, 1));
  513. }
  514. else // c2 >= 0 or a1 >= 0
  515. {
  516. // Two complex-conjugate pairs. The values alpha, D0
  517. // and D1 are those of the if-block.
  518. // Complex z0 = (alpha - i*sqrt(-D0))/2;
  519. // Complex z0conj = (alpha + i*sqrt(-D0))/2;
  520. // Complex z1 = (-alpha - i*sqrt(-D1))/2;
  521. // Complex z1conj = (-alpha + i*sqrt(-D1))/2;
  522. GTE_ROOTS_LOW_DEGREE_BLOCK(17);
  523. }
  524. }
  525. else if (delta < zero)
  526. {
  527. // Two simple real roots, one complex-conjugate pair.
  528. std::map<Real, int> rmCubicMap;
  529. SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8,
  530. rmCubicMap);
  531. Rational t = (Rational)rmCubicMap.rbegin()->first;
  532. Rational alphaSqr = rat2 * t - c2;
  533. Rational alpha = (Rational)std::sqrt(std::max((double)alphaSqr, 0.0));
  534. double sgnC1;
  535. if (c1 > zero)
  536. {
  537. sgnC1 = 1.0; // Leads to BLOCK(18)
  538. }
  539. else
  540. {
  541. sgnC1 = -1.0; // Leads to BLOCK(19)
  542. }
  543. Rational arg = t * t - c0;
  544. Rational beta = (Rational)(sgnC1 * std::sqrt(std::max((double)arg, 0.0)));
  545. Rational root0, root1;
  546. if (sgnC1 > 0.0)
  547. {
  548. Rational D1 = alphaSqr - rat4 * (t - beta);
  549. Rational sqrtD1 = (Rational)std::sqrt(std::max((double)D1, 0.0));
  550. root0 = (-alpha - sqrtD1) / rat2;
  551. root1 = (-alpha + sqrtD1) / rat2;
  552. // One complex conjugate pair.
  553. // Complex z0 = (alpha - i*sqrt(-D0))/2;
  554. // Complex z0conj = (alpha + i*sqrt(-D0))/2;
  555. GTE_ROOTS_LOW_DEGREE_BLOCK(18);
  556. }
  557. else
  558. {
  559. Rational D0 = alphaSqr - rat4 * (t + beta);
  560. Rational sqrtD0 = (Rational)std::sqrt(std::max((double)D0, 0.0));
  561. root0 = (alpha - sqrtD0) / rat2;
  562. root1 = (alpha + sqrtD0) / rat2;
  563. // One complex conjugate pair.
  564. // Complex z0 = (-alpha - i*sqrt(-D1))/2;
  565. // Complex z0conj = (-alpha + i*sqrt(-D1))/2;
  566. GTE_ROOTS_LOW_DEGREE_BLOCK(19);
  567. }
  568. rmMap.insert(std::make_pair(root0, 1));
  569. rmMap.insert(std::make_pair(root1, 1));
  570. }
  571. else // delta = 0
  572. {
  573. if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
  574. {
  575. // One double real root, one complex-conjugate pair.
  576. Rational const rat9 = 9;
  577. Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
  578. rmMap.insert(std::make_pair(root0, 2));
  579. // One complex conjugate pair.
  580. // Complex z0 = -root0 - i*sqrt(c2 + root0^2);
  581. // Complex z0conj = -root0 + i*sqrt(c2 + root0^2);
  582. GTE_ROOTS_LOW_DEGREE_BLOCK(20);
  583. }
  584. else
  585. {
  586. Rational const rat3 = 3;
  587. if (a0 != zero)
  588. {
  589. // One double real root, two simple real roots.
  590. Rational const rat9 = 9;
  591. Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
  592. Rational alpha = rat2 * root0;
  593. Rational beta = c2 + rat3 * root0 * root0;
  594. Rational discr = alpha * alpha - rat4 * beta;
  595. Rational temp1 = (Rational)std::sqrt((double)discr);
  596. Rational root1 = (-alpha - temp1) / rat2;
  597. Rational root2 = (-alpha + temp1) / rat2;
  598. rmMap.insert(std::make_pair(root0, 2));
  599. rmMap.insert(std::make_pair(root1, 1));
  600. rmMap.insert(std::make_pair(root2, 1));
  601. GTE_ROOTS_LOW_DEGREE_BLOCK(21);
  602. }
  603. else
  604. {
  605. // One triple real root, one simple real root.
  606. Rational root0 = -rat3 * c1 / (rat4 * c2);
  607. Rational root1 = -rat3 * root0;
  608. rmMap.insert(std::make_pair(root0, 3));
  609. rmMap.insert(std::make_pair(root1, 1));
  610. GTE_ROOTS_LOW_DEGREE_BLOCK(22);
  611. }
  612. }
  613. }
  614. }
  615. template <typename Rational>
  616. static void SolveBiquadratic(Rational const& c0, Rational const& c2,
  617. std::map<Rational, int>& rmMap)
  618. {
  619. // Solve 0 = x^4 + c2*x^2 + c0 = (x^2 + c2/2)^2 + a1, where
  620. // a1 = c0 - c2^2/2. We know that c0 != 0 at the time of the
  621. // function call, so x = 0 is not a root. The condition c1 = 0
  622. // implies the quartic Delta = 256*c0*a1^2.
  623. Rational const zero = 0, rat2 = 2, rat256 = 256;
  624. Rational c2Half = c2 / rat2;
  625. Rational a1 = c0 - c2Half * c2Half;
  626. Rational delta = rat256 * c0 * a1 * a1;
  627. if (delta > zero)
  628. {
  629. if (c2 < zero)
  630. {
  631. if (a1 < zero)
  632. {
  633. // Four simple roots.
  634. Rational temp0 = (Rational)std::sqrt(-(double)a1);
  635. Rational temp1 = -c2Half - temp0;
  636. Rational temp2 = -c2Half + temp0;
  637. Rational root1 = (Rational)std::sqrt((double)temp1);
  638. Rational root0 = -root1;
  639. Rational root2 = (Rational)std::sqrt((double)temp2);
  640. Rational root3 = -root2;
  641. rmMap.insert(std::make_pair(root0, 1));
  642. rmMap.insert(std::make_pair(root1, 1));
  643. rmMap.insert(std::make_pair(root2, 1));
  644. rmMap.insert(std::make_pair(root3, 1));
  645. GTE_ROOTS_LOW_DEGREE_BLOCK(23);
  646. }
  647. else // a1 > 0
  648. {
  649. // Two simple complex conjugate pairs.
  650. // double thetaDiv2 = atan2(sqrt(a1), -c2/2) / 2.0;
  651. // double cs = cos(thetaDiv2), sn = sin(thetaDiv2);
  652. // double length = pow(c0, 0.25);
  653. // Complex z0 = length*(cs + i*sn);
  654. // Complex z0conj = length*(cs - i*sn);
  655. // Complex z1 = length*(-cs + i*sn);
  656. // Complex z1conj = length*(-cs - i*sn);
  657. GTE_ROOTS_LOW_DEGREE_BLOCK(24);
  658. }
  659. }
  660. else // c2 >= 0
  661. {
  662. // Two simple complex conjugate pairs.
  663. // Complex z0 = -i*sqrt(c2/2 - sqrt(-a1));
  664. // Complex z0conj = +i*sqrt(c2/2 - sqrt(-a1));
  665. // Complex z1 = -i*sqrt(c2/2 + sqrt(-a1));
  666. // Complex z1conj = +i*sqrt(c2/2 + sqrt(-a1));
  667. GTE_ROOTS_LOW_DEGREE_BLOCK(25);
  668. }
  669. }
  670. else if (delta < zero)
  671. {
  672. // Two simple real roots.
  673. Rational temp0 = (Rational)std::sqrt(-(double)a1);
  674. Rational temp1 = -c2Half + temp0;
  675. Rational root1 = (Rational)std::sqrt((double)temp1);
  676. Rational root0 = -root1;
  677. rmMap.insert(std::make_pair(root0, 1));
  678. rmMap.insert(std::make_pair(root1, 1));
  679. // One complex conjugate pair.
  680. // Complex z0 = -i*sqrt(c2/2 + sqrt(-a1));
  681. // Complex z0conj = +i*sqrt(c2/2 + sqrt(-a1));
  682. GTE_ROOTS_LOW_DEGREE_BLOCK(26);
  683. }
  684. else // delta = 0
  685. {
  686. if (c2 < zero)
  687. {
  688. // Two double real roots.
  689. Rational root1 = (Rational)std::sqrt(-(double)c2Half);
  690. Rational root0 = -root1;
  691. rmMap.insert(std::make_pair(root0, 2));
  692. rmMap.insert(std::make_pair(root1, 2));
  693. GTE_ROOTS_LOW_DEGREE_BLOCK(27);
  694. }
  695. else // c2 > 0
  696. {
  697. // Two double complex conjugate pairs.
  698. // Complex z0 = -i*sqrt(c2/2); // multiplicity 2
  699. // Complex z0conj = +i*sqrt(c2/2); // multiplicity 2
  700. GTE_ROOTS_LOW_DEGREE_BLOCK(28);
  701. }
  702. }
  703. }
  704. // Support for the GetNumRoots* functions.
  705. template <typename Rational>
  706. static void GetRootInfoDepressedQuadratic(Rational const& c0,
  707. std::vector<int>& info)
  708. {
  709. Rational const zero = 0;
  710. if (c0 < zero)
  711. {
  712. // Two simple roots.
  713. info.push_back(1);
  714. info.push_back(1);
  715. }
  716. else if (c0 == zero)
  717. {
  718. // One double root.
  719. info.push_back(2); // root is zero
  720. }
  721. else // c0 > 0
  722. {
  723. // A complex-conjugate pair of roots.
  724. }
  725. }
  726. template <typename Rational>
  727. static void GetRootInfoDepressedCubic(Rational const& c0,
  728. Rational const& c1, std::vector<int>& info)
  729. {
  730. // Handle the special case of c0 = 0, in which case the polynomial
  731. // reduces to a depressed quadratic.
  732. Rational const zero = 0;
  733. if (c0 == zero)
  734. {
  735. if (c1 == zero)
  736. {
  737. info.push_back(3); // triple root of zero
  738. }
  739. else
  740. {
  741. info.push_back(1); // simple root of zero
  742. GetRootInfoDepressedQuadratic(c1, info);
  743. }
  744. return;
  745. }
  746. Rational const rat4 = 4, rat27 = 27;
  747. Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
  748. if (delta > zero)
  749. {
  750. // Three simple real roots.
  751. info.push_back(1);
  752. info.push_back(1);
  753. info.push_back(1);
  754. }
  755. else if (delta < zero)
  756. {
  757. // One simple real root.
  758. info.push_back(1);
  759. }
  760. else // delta = 0
  761. {
  762. // One simple real root and one double real root.
  763. info.push_back(1);
  764. info.push_back(2);
  765. }
  766. }
  767. template <typename Rational>
  768. static void GetRootInfoDepressedQuartic(Rational const& c0,
  769. Rational const& c1, Rational const& c2, std::vector<int>& info)
  770. {
  771. // Handle the special case of c0 = 0, in which case the polynomial
  772. // reduces to a depressed cubic.
  773. Rational const zero = 0;
  774. if (c0 == zero)
  775. {
  776. if (c1 == zero)
  777. {
  778. if (c2 == zero)
  779. {
  780. info.push_back(4); // quadruple root of zero
  781. }
  782. else
  783. {
  784. info.push_back(2); // double root of zero
  785. GetRootInfoDepressedQuadratic(c2, info);
  786. }
  787. }
  788. else
  789. {
  790. info.push_back(1); // simple root of zero
  791. GetRootInfoDepressedCubic(c1, c2, info);
  792. }
  793. return;
  794. }
  795. // Handle the special case of c1 = 0, in which case the quartic is
  796. // a biquadratic
  797. // x^4 + c1*x^2 + c0 = (x^2 + c2/2)^2 + (c0 - c2^2/4)
  798. if (c1 == zero)
  799. {
  800. GetRootInfoBiquadratic(c0, c2, info);
  801. return;
  802. }
  803. // At this time, c0 != 0 and c1 != 0, which is a requirement for
  804. // the general solver that must use a root of a special cubic
  805. // polynomial.
  806. Rational const rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
  807. Rational const rat27 = 27, rat36 = 36;
  808. Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
  809. Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
  810. (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
  811. rat16 * c0sqr);
  812. Rational a0 = rat12 * c0 + c2sqr;
  813. Rational a1 = rat4 * c0 - c2sqr;
  814. if (delta > zero)
  815. {
  816. if (c2 < zero && a1 < zero)
  817. {
  818. // Four simple real roots.
  819. info.push_back(1);
  820. info.push_back(1);
  821. info.push_back(1);
  822. info.push_back(1);
  823. }
  824. else // c2 >= 0 or a1 >= 0
  825. {
  826. // Two complex-conjugate pairs.
  827. }
  828. }
  829. else if (delta < zero)
  830. {
  831. // Two simple real roots, one complex-conjugate pair.
  832. info.push_back(1);
  833. info.push_back(1);
  834. }
  835. else // delta = 0
  836. {
  837. if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
  838. {
  839. // One double real root, one complex-conjugate pair.
  840. info.push_back(2);
  841. }
  842. else
  843. {
  844. if (a0 != zero)
  845. {
  846. // One double real root, two simple real roots.
  847. info.push_back(2);
  848. info.push_back(1);
  849. info.push_back(1);
  850. }
  851. else
  852. {
  853. // One triple real root, one simple real root.
  854. info.push_back(3);
  855. info.push_back(1);
  856. }
  857. }
  858. }
  859. }
  860. template <typename Rational>
  861. static void GetRootInfoBiquadratic(Rational const& c0,
  862. Rational const& c2, std::vector<int>& info)
  863. {
  864. // Solve 0 = x^4 + c2*x^2 + c0 = (x^2 + c2/2)^2 + a1, where
  865. // a1 = c0 - c2^2/2. We know that c0 != 0 at the time of the
  866. // function call, so x = 0 is not a root. The condition c1 = 0
  867. // implies the quartic Delta = 256*c0*a1^2.
  868. Rational const zero = 0, rat2 = 2, rat256 = 256;
  869. Rational c2Half = c2 / rat2;
  870. Rational a1 = c0 - c2Half * c2Half;
  871. Rational delta = rat256 * c0 * a1 * a1;
  872. if (delta > zero)
  873. {
  874. if (c2 < zero)
  875. {
  876. if (a1 < zero)
  877. {
  878. // Four simple roots.
  879. info.push_back(1);
  880. info.push_back(1);
  881. info.push_back(1);
  882. info.push_back(1);
  883. }
  884. else // a1 > 0
  885. {
  886. // Two simple complex conjugate pairs.
  887. }
  888. }
  889. else // c2 >= 0
  890. {
  891. // Two simple complex conjugate pairs.
  892. }
  893. }
  894. else if (delta < zero)
  895. {
  896. // Two simple real roots, one complex conjugate pair.
  897. info.push_back(1);
  898. info.push_back(1);
  899. }
  900. else // delta = 0
  901. {
  902. if (c2 < zero)
  903. {
  904. // Two double real roots.
  905. info.push_back(2);
  906. info.push_back(2);
  907. }
  908. else // c2 > 0
  909. {
  910. // Two double complex conjugate pairs.
  911. }
  912. }
  913. }
  914. // Support for the Find functions.
  915. static int FindRecursive(int degree, Real const* c, Real tmin, Real tmax,
  916. unsigned int maxIterations, Real* roots)
  917. {
  918. // The base of the recursion.
  919. Real const zero = (Real)0;
  920. Real root = zero;
  921. if (degree == 1)
  922. {
  923. int numRoots;
  924. if (c[1] != zero)
  925. {
  926. root = -c[0] / c[1];
  927. numRoots = 1;
  928. }
  929. else if (c[0] == zero)
  930. {
  931. root = zero;
  932. numRoots = 1;
  933. }
  934. else
  935. {
  936. numRoots = 0;
  937. }
  938. if (numRoots > 0 && tmin <= root && root <= tmax)
  939. {
  940. roots[0] = root;
  941. return 1;
  942. }
  943. return 0;
  944. }
  945. // Find the roots of the derivative polynomial scaled by 1/degree.
  946. // The scaling avoids the factorial growth in the coefficients;
  947. // for example, without the scaling, the high-order term x^d
  948. // becomes (d!)*x through multiple differentiations. With the
  949. // scaling we instead get x. This leads to better numerical
  950. // behavior of the root finder.
  951. int derivDegree = degree - 1;
  952. std::vector<Real> derivCoeff(derivDegree + 1);
  953. std::vector<Real> derivRoots(derivDegree);
  954. for (int i = 0; i <= derivDegree; ++i)
  955. {
  956. derivCoeff[i] = c[i + 1] * (Real)(i + 1) / (Real)degree;
  957. }
  958. int numDerivRoots = FindRecursive(degree - 1, &derivCoeff[0], tmin, tmax,
  959. maxIterations, &derivRoots[0]);
  960. int numRoots = 0;
  961. if (numDerivRoots > 0)
  962. {
  963. // Find root on [tmin,derivRoots[0]].
  964. if (Find(degree, c, tmin, derivRoots[0], maxIterations, root))
  965. {
  966. roots[numRoots++] = root;
  967. }
  968. // Find root on [derivRoots[i],derivRoots[i+1]].
  969. for (int i = 0; i <= numDerivRoots - 2; ++i)
  970. {
  971. if (Find(degree, c, derivRoots[i], derivRoots[i + 1],
  972. maxIterations, root))
  973. {
  974. roots[numRoots++] = root;
  975. }
  976. }
  977. // Find root on [derivRoots[numDerivRoots-1],tmax].
  978. if (Find(degree, c, derivRoots[numDerivRoots - 1], tmax,
  979. maxIterations, root))
  980. {
  981. roots[numRoots++] = root;
  982. }
  983. }
  984. else
  985. {
  986. // The polynomial is monotone on [tmin,tmax], so has at most one root.
  987. if (Find(degree, c, tmin, tmax, maxIterations, root))
  988. {
  989. roots[numRoots++] = root;
  990. }
  991. }
  992. return numRoots;
  993. }
  994. static Real Evaluate(int degree, Real const* c, Real t)
  995. {
  996. int i = degree;
  997. Real result = c[i];
  998. while (--i >= 0)
  999. {
  1000. result = t * result + c[i];
  1001. }
  1002. return result;
  1003. }
  1004. };
  1005. }