48 template <
typename Real>
63 template <
typename Rational>
65 Rational
const& p2, std::map<Real, int>& rmMap);
67 template <
typename Rational>
68 static void SolveCubic(Rational
const& p0, Rational
const& p1,
69 Rational
const& p2, Rational
const& p3, std::map<Real, int>& rmMap);
71 template <
typename Rational>
72 static void SolveQuartic(Rational
const& p0, Rational
const& p1,
73 Rational
const& p2, Rational
const& p3, Rational
const& p4,
74 std::map<Real, int>& rmMap);
79 template <
typename Rational>
81 Rational
const& p2, std::vector<int>& info);
83 template <
typename Rational>
85 Rational
const& p2, Rational
const& p3, std::vector<int>& info);
87 template <
typename Rational>
89 Rational
const& p2, Rational
const& p3, Rational
const& p4,
90 std::vector<int>& info);
98 static int Find(
int degree, Real
const*
c,
unsigned int maxIterations,
103 static bool Find(
int degree, Real
const* c, Real tmin, Real tmax,
104 unsigned int maxIterations, Real& root);
108 template <
typename Rational>
110 std::map<Rational, int>& rmMap);
112 template <
typename Rational>
114 std::map<Rational, int>& rmMap);
116 template <
typename Rational>
118 Rational
const& c2, std::map<Rational, int>& rmMap);
120 template <
typename Rational>
122 std::map<Rational, int>& rmMap);
125 template <
typename Rational>
127 std::vector<int>& info);
129 template <
typename Rational>
131 Rational
const& c1, std::vector<int>& info);
133 template <
typename Rational>
135 Rational
const& c1, Rational
const& c2, std::vector<int>& info);
137 template <
typename Rational>
139 Rational
const& c2, std::vector<int>& info);
142 static int FindRecursive(
int degree, Real
const* c, Real tmin, Real tmax,
143 unsigned int maxIterations, Real* roots);
145 static Real
Evaluate(
int degree, Real
const* c, Real
t);
150 #if defined(GTE_ROOTS_LOW_DEGREE_UNIT_TEST) 151 extern void RootsLowDegreeBlock(
int);
152 #define GTE_ROOTS_LOW_DEGREE_BLOCK(block) RootsLowDegreeBlock(block) 154 #define GTE_ROOTS_LOW_DEGREE_BLOCK(block) 158 template <
typename Real>
159 template <
typename Rational>
161 Rational
const& p1, Rational
const& p2, std::map<Real, int>& rmMap)
163 Rational
const rat2 = 2;
164 Rational q0 = p0 / p2;
165 Rational q1 = p1 / p2;
166 Rational q1half = q1 / rat2;
167 Rational c0 = q0 - q1half * q1half;
169 std::map<Rational, int> rmLocalMap;
173 for (
auto& rm : rmLocalMap)
175 Rational root = rm.first - q1half;
176 rmMap.insert(std::make_pair((Real)root, rm.second));
180 template <
typename Real>
181 template <
typename Rational>
183 Rational
const& p1, Rational
const& p2, Rational
const& p3,
184 std::map<Real, int>& rmMap)
186 Rational
const rat2 = 2, rat3 = 3;
187 Rational q0 = p0 / p3;
188 Rational q1 = p1 / p3;
189 Rational q2 = p2 / p3;
190 Rational q2third = q2 / rat3;
191 Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
192 Rational c1 = q1 - q2 * q2third;
194 std::map<Rational, int> rmLocalMap;
198 for (
auto& rm : rmLocalMap)
200 Rational root = rm.first - q2third;
201 rmMap.insert(std::make_pair((Real)root, rm.second));
205 template <
typename Real>
206 template <
typename Rational>
208 Rational
const& p1, Rational
const& p2, Rational
const& p3,
209 Rational
const& p4, std::map<Real, int>& rmMap)
211 Rational
const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
212 Rational q0 = p0 / p4;
213 Rational q1 = p1 / p4;
214 Rational q2 = p2 / p4;
215 Rational q3 = p3 / p4;
216 Rational q3fourth = q3 / rat4;
217 Rational q3fourthSqr = q3fourth * q3fourth;
218 Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
219 Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
220 Rational c2 = q2 - rat6 * q3fourthSqr;
222 std::map<Rational, int> rmLocalMap;
226 for (
auto& rm : rmLocalMap)
228 Rational root = rm.first - q3fourth;
229 rmMap.insert(std::make_pair((Real)root, rm.second));
233 template <
typename Real>
234 template <
typename Rational>
236 Rational
const& p1, Rational
const& p2, std::vector<int>& info)
238 Rational
const rat2 = 2;
239 Rational q0 = p0 / p2;
240 Rational q1 = p1 / p2;
241 Rational q1half = q1 / rat2;
242 Rational c0 = q0 - q1half * q1half;
249 template <
typename Real>
250 template <
typename Rational>
252 Rational
const& p1, Rational
const& p2, Rational
const& p3,
253 std::vector<int>& info)
255 Rational
const rat2 = 2, rat3 = 3;
256 Rational q0 = p0 / p3;
257 Rational q1 = p1 / p3;
258 Rational q2 = p2 / p3;
259 Rational q2third = q2 / rat3;
260 Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
261 Rational c1 = q1 - q2 * q2third;
268 template <
typename Real>
269 template <
typename Rational>
271 Rational
const& p1, Rational
const& p2, Rational
const& p3,
272 Rational
const& p4, std::vector<int>& info)
274 Rational
const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
275 Rational q0 = p0 / p4;
276 Rational q1 = p1 / p4;
277 Rational q2 = p2 / p4;
278 Rational q3 = p3 / p4;
279 Rational q3fourth = q3 / rat4;
280 Rational q3fourthSqr = q3fourth * q3fourth;
281 Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
282 Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
283 Rational c2 = q2 - rat6 * q3fourthSqr;
290 template <
typename Real>
292 unsigned int maxIterations, Real* roots)
294 if (degree >= 0 && c)
296 Real
const zero = (Real)0;
297 while (degree >= 0 && c[degree] == zero)
305 Real
const one = (Real)1;
306 Real invLeading = one / c[degree];
307 Real maxValue = zero;
308 for (
int i = 0; i < degree; ++i)
311 if (value > maxValue)
316 Real bound = one + maxValue;
318 return FindRecursive(degree, c, -bound, bound, maxIterations,
321 else if (degree == 0)
340 template <
typename Real>
342 Real tmax,
unsigned int maxIterations, Real& root)
344 Real
const zero = (Real)0;
345 Real pmin =
Evaluate(degree, c, tmin);
351 Real pmax =
Evaluate(degree, c, tmax);
358 if (pmin*pmax > zero)
370 for (
unsigned int i = 1; i <= maxIterations; ++i)
372 root = ((Real)0.5) * (tmin + tmax);
376 if (root == tmin || root == tmax)
382 Real product = p * pmin;
388 else if (product > zero)
402 template <
typename Real>
403 template <
typename Rational>
405 std::map<Rational, int>& rmMap)
407 Rational
const zero = 0;
411 Rational root1 = (Rational)sqrt(-(
double)c0);
412 Rational root0 = -root1;
413 rmMap.insert(std::make_pair(root0, 1));
414 rmMap.insert(std::make_pair(root1, 1));
420 rmMap.insert(std::make_pair(zero, 2));
432 template <
typename Real>
433 template <
typename Rational>
435 Rational
const& c1, std::map<Rational, int>& rmMap)
439 Rational
const zero = 0;
443 auto iter = rmMap.find(zero);
444 if (iter != rmMap.end())
455 rmMap.insert(std::make_pair(zero, 1));
462 double const oneThird = 1.0 / 3.0;
469 root0 = (Rational)-pow((
double)c0, oneThird);
474 root0 = (Rational)pow(-(
double)c0, oneThird);
477 rmMap.insert(std::make_pair(root0, 1));
486 Rational
const rat2 = 2, rat3 = 3, rat4 = 4, rat27 = 27, rat108 = 108;
487 Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
491 Rational deltaDiv108 = delta / rat108;
492 Rational betaRe = -c0 / rat2;
493 Rational betaIm = (Rational)sqrt((
double)deltaDiv108);
494 Rational theta = (Rational)atan2((
double)betaIm, (double)betaRe);
495 Rational thetaDiv3 = theta / rat3;
496 double angle = (double)thetaDiv3;
497 Rational cs = (Rational)cos(angle);
498 Rational sn = (Rational)sin(angle);
499 Rational rhoSqr = betaRe * betaRe + betaIm * betaIm;
500 Rational rhoPowThird = (Rational)pow((
double)rhoSqr, 1.0 / 6.0);
501 Rational temp0 = rhoPowThird * cs;
502 Rational temp1 = rhoPowThird * sn * (Rational)sqrt(3.0);
503 Rational root0 = rat2 * temp0;
504 Rational root1 = -temp0 - temp1;
505 Rational root2 = -temp0 + temp1;
506 rmMap.insert(std::make_pair(root0, 1));
507 rmMap.insert(std::make_pair(root1, 1));
508 rmMap.insert(std::make_pair(root2, 1));
511 else if (delta < zero)
514 Rational deltaDiv108 = delta / rat108;
515 Rational temp0 = -c0 / rat2;
516 Rational temp1 = (Rational)sqrt(-(
double)deltaDiv108);
517 Rational temp2 = temp0 - temp1;
518 Rational temp3 = temp0 + temp1;
521 temp2 = (Rational)pow((
double)temp2, oneThird);
526 temp2 = (Rational)-pow(-(
double)temp2, oneThird);
531 temp3 = (Rational)pow((
double)temp3, oneThird);
536 temp3 = (Rational)-pow(-(
double)temp3, oneThird);
539 Rational root0 = temp2 + temp3;
540 rmMap.insert(std::make_pair(root0, 1));
549 Rational root0 = -rat3 * c0 / (rat2 * c1);
550 Rational root1 = -rat2 * root0;
551 rmMap.insert(std::make_pair(root0, 2));
552 rmMap.insert(std::make_pair(root1, 1));
557 template <
typename Real>
558 template <
typename Rational>
560 Rational
const& c1, Rational
const& c2, std::map<Rational, int>& rmMap)
564 Rational
const zero = 0;
568 auto iter = rmMap.find(zero);
569 if (iter != rmMap.end())
580 rmMap.insert(std::make_pair(zero, 1));
596 Rational
const rat2 = 2, rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
597 Rational
const rat27 = 27, rat36 = 36;
598 Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
599 Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
600 (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
602 Rational a0 = rat12 * c0 + c2sqr;
603 Rational a1 = rat4 * c0 - c2sqr;
607 if (c2 < zero && a1 < zero)
610 std::map<Real, int> rmCubicMap;
611 SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8,
613 Rational
t = (Rational)rmCubicMap.rbegin()->first;
614 Rational alphaSqr = rat2 * t - c2;
615 Rational
alpha = (Rational)sqrt((
double)alphaSqr);
627 Rational arg = t * t - c0;
628 Rational beta = (Rational)(sgnC1 * sqrt(std::max((
double)arg, 0.0)));
629 Rational D0 = alphaSqr - rat4 * (t + beta);
630 Rational sqrtD0 = (Rational)sqrt(std::max((
double)D0, 0.0));
631 Rational D1 = alphaSqr - rat4 * (t - beta);
632 Rational sqrtD1 = (Rational)sqrt(std::max((
double)D1, 0.0));
633 Rational root0 = (alpha - sqrtD0) / rat2;
634 Rational root1 = (alpha + sqrtD0) / rat2;
635 Rational root2 = (-alpha - sqrtD1) / rat2;
636 Rational root3 = (-alpha + sqrtD1) / rat2;
637 rmMap.insert(std::make_pair(root0, 1));
638 rmMap.insert(std::make_pair(root1, 1));
639 rmMap.insert(std::make_pair(root2, 1));
640 rmMap.insert(std::make_pair(root3, 1));
653 else if (delta < zero)
656 std::map<Real, int> rmCubicMap;
657 SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8,
659 Rational
t = (Rational)rmCubicMap.rbegin()->first;
660 Rational alphaSqr = rat2 * t - c2;
661 Rational
alpha = (Rational)sqrt(std::max((
double)alphaSqr, 0.0));
671 Rational arg = t * t - c0;
672 Rational beta = (Rational)(sgnC1 * sqrt(std::max((
double)arg, 0.0)));
673 Rational root0, root1;
676 Rational D1 = alphaSqr - rat4 * (t - beta);
677 Rational sqrtD1 = (Rational)sqrt(std::max((
double)D1, 0.0));
678 root0 = (-alpha - sqrtD1) / rat2;
679 root1 = (-alpha + sqrtD1) / rat2;
688 Rational D0 = alphaSqr - rat4 * (t + beta);
689 Rational sqrtD0 = (Rational)sqrt(std::max((
double)D0, 0.0));
690 root0 = (alpha - sqrtD0) / rat2;
691 root1 = (alpha + sqrtD0) / rat2;
698 rmMap.insert(std::make_pair(root0, 1));
699 rmMap.insert(std::make_pair(root1, 1));
703 if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
706 Rational
const rat9 = 9;
707 Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
708 rmMap.insert(std::make_pair(root0, 2));
717 Rational
const rat3 = 3;
721 Rational
const rat9 = 9;
722 Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
723 Rational
alpha = rat2 * root0;
724 Rational beta = c2 + rat3 * root0 * root0;
725 Rational discr = alpha * alpha - rat4 * beta;
726 Rational temp1 = (Rational)sqrt((
double)discr);
727 Rational root1 = (-alpha - temp1) / rat2;
728 Rational root2 = (-alpha + temp1) / rat2;
729 rmMap.insert(std::make_pair(root0, 2));
730 rmMap.insert(std::make_pair(root1, 1));
731 rmMap.insert(std::make_pair(root2, 1));
737 Rational root0 = -rat3 * c1 / (rat4 * c2);
738 Rational root1 = -rat3 * root0;
739 rmMap.insert(std::make_pair(root0, 3));
740 rmMap.insert(std::make_pair(root1, 1));
747 template <
typename Real>
748 template <
typename Rational>
750 Rational
const& c2, std::map<Rational, int>& rmMap)
757 Rational
const zero = 0, rat2 = 2, rat256 = 256;
758 Rational c2Half = c2 / rat2;
759 Rational a1 = c0 - c2Half * c2Half;
760 Rational delta = rat256 * c0 * a1 * a1;
768 Rational temp0 = (Rational)sqrt(-(
double)a1);
769 Rational temp1 = -c2Half - temp0;
770 Rational temp2 = -c2Half + temp0;
771 Rational root1 = (Rational)sqrt((
double)temp1);
772 Rational root0 = -root1;
773 Rational root2 = (Rational)sqrt((
double)temp2);
774 Rational root3 = -root2;
775 rmMap.insert(std::make_pair(root0, 1));
776 rmMap.insert(std::make_pair(root1, 1));
777 rmMap.insert(std::make_pair(root2, 1));
778 rmMap.insert(std::make_pair(root3, 1));
804 else if (delta < zero)
807 Rational temp0 = (Rational)sqrt(-(
double)a1);
808 Rational temp1 = -c2Half + temp0;
809 Rational root1 = (Rational)sqrt((
double)temp1);
810 Rational root0 = -root1;
811 rmMap.insert(std::make_pair(root0, 1));
812 rmMap.insert(std::make_pair(root1, 1));
824 Rational root1 = (Rational)sqrt(-(
double)c2Half);
825 Rational root0 = -root1;
826 rmMap.insert(std::make_pair(root0, 2));
827 rmMap.insert(std::make_pair(root1, 2));
840 template <
typename Real>
841 template <
typename Rational>
843 std::vector<int>& info)
845 Rational
const zero = 0;
863 template <
typename Real>
864 template <
typename Rational>
866 Rational
const& c1, std::vector<int>& info)
870 Rational
const zero = 0;
885 Rational
const rat4 = 4, rat27 = 27;
886 Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
894 else if (delta < zero)
907 template <
typename Real>
908 template <
typename Rational>
910 Rational
const& c1, Rational
const& c2, std::vector<int>& info)
914 Rational
const zero = 0;
947 Rational
const rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
948 Rational
const rat27 = 27, rat36 = 36;
949 Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
950 Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
951 (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
953 Rational a0 = rat12 * c0 + c2sqr;
954 Rational a1 = rat4 * c0 - c2sqr;
958 if (c2 < zero && a1 < zero)
971 else if (delta < zero)
979 if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
1003 template <
typename Real>
1004 template <
typename Rational>
1006 Rational
const& c2, std::vector<int>& info)
1013 Rational
const zero = 0, rat2 = 2, rat256 = 256;
1014 Rational c2Half = c2 / rat2;
1015 Rational a1 = c0 - c2Half * c2Half;
1016 Rational delta = rat256 * c0 * a1 * a1;
1039 else if (delta < zero)
1060 template <
typename Real>
1062 Real tmin, Real tmax,
unsigned int maxIterations, Real* roots)
1065 Real
const zero = (Real)0;
1072 root = -c[0] / c[1];
1075 else if (c[0] == zero)
1085 if (numRoots > 0 && tmin <= root && root <= tmax)
1098 int derivDegree = degree - 1;
1099 std::vector<Real> derivCoeff(derivDegree + 1);
1100 std::vector<Real> derivRoots(derivDegree);
1101 for (
int i = 0; i <= derivDegree; ++i)
1103 derivCoeff[i] = c[i + 1] * (Real)(i + 1) / (Real)degree;
1105 int numDerivRoots =
FindRecursive(degree - 1, &derivCoeff[0], tmin, tmax,
1106 maxIterations, &derivRoots[0]);
1109 if (numDerivRoots > 0)
1112 if (
Find(degree, c, tmin, derivRoots[0], maxIterations, root))
1114 roots[numRoots++] = root;
1118 for (
int i = 0; i <= numDerivRoots - 2; ++i)
1120 if (
Find(degree, c, derivRoots[i], derivRoots[i + 1],
1121 maxIterations, root))
1123 roots[numRoots++] = root;
1128 if (
Find(degree, c, derivRoots[numDerivRoots - 1], tmax,
1129 maxIterations, root))
1131 roots[numRoots++] = root;
1137 if (
Find(degree, c, tmin, tmax, maxIterations, root))
1139 roots[numRoots++] = root;
1145 template <
typename Real>
1152 result = t * result + c[i];
static int FindRecursive(int degree, Real const *c, Real tmin, Real tmax, unsigned int maxIterations, Real *roots)
GLfloat GLfloat GLfloat alpha
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
static void GetRootInfoCubic(Rational const &p0, Rational const &p1, Rational const &p2, Rational const &p3, std::vector< int > &info)
static void SolveDepressedQuadratic(Rational const &c0, std::map< Rational, int > &rmMap)
GLsizei const GLfloat * value
static void GetRootInfoDepressedQuadratic(Rational const &c0, std::vector< int > &info)
static void GetRootInfoQuartic(Rational const &p0, Rational const &p1, Rational const &p2, Rational const &p3, Rational const &p4, std::vector< int > &info)
#define GTE_ROOTS_LOW_DEGREE_BLOCK(block)
static void SolveBiquadratic(Rational const &c0, Rational const &c2, std::map< Rational, int > &rmMap)
static void SolveQuadratic(Rational const &p0, Rational const &p1, Rational const &p2, std::map< Real, int > &rmMap)
static void GetRootInfoBiquadratic(Rational const &c0, Rational const &c2, std::vector< int > &info)
static void SolveDepressedQuartic(Rational const &c0, Rational const &c1, Rational const &c2, std::map< Rational, int > &rmMap)
static void GetRootInfoDepressedCubic(Rational const &c0, Rational const &c1, std::vector< int > &info)
static Real Evaluate(int degree, Real const *c, Real t)
static void GetRootInfoDepressedQuartic(Rational const &c0, Rational const &c1, Rational const &c2, std::vector< int > &info)
static void GetRootInfoQuadratic(Rational const &p0, Rational const &p1, Rational const &p2, std::vector< int > &info)
static void SolveQuartic(Rational const &p0, Rational const &p1, Rational const &p2, Rational const &p3, Rational const &p4, std::map< Real, int > &rmMap)
static void SolveCubic(Rational const &p0, Rational const &p1, Rational const &p2, Rational const &p3, std::map< Real, int > &rmMap)
static int Find(int degree, Real const *c, unsigned int maxIterations, Real *roots)
static void SolveDepressedCubic(Rational const &c0, Rational const &c1, std::map< Rational, int > &rmMap)