123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068 |
- #pragma once
- #include <Mathematics/Math.h>
- #include <algorithm>
- #include <map>
- #include <vector>
- #if defined(GTE_ROOTS_LOW_DEGREE_UNIT_TEST)
- extern void RootsLowDegreeBlock(int);
- #define GTE_ROOTS_LOW_DEGREE_BLOCK(block) RootsLowDegreeBlock(block)
- #else
- #define GTE_ROOTS_LOW_DEGREE_BLOCK(block)
- #endif
- namespace WwiseGTE
- {
- template <typename Real>
- class RootsPolynomial
- {
- public:
-
-
-
-
-
-
-
-
-
-
-
- template <typename Rational>
- static void SolveQuadratic(Rational const& p0, Rational const& p1,
- Rational const& p2, std::map<Real, int>& rmMap)
- {
- Rational const rat2 = 2;
- Rational q0 = p0 / p2;
- Rational q1 = p1 / p2;
- Rational q1half = q1 / rat2;
- Rational c0 = q0 - q1half * q1half;
- std::map<Rational, int> rmLocalMap;
- SolveDepressedQuadratic(c0, rmLocalMap);
- rmMap.clear();
- for (auto& rm : rmLocalMap)
- {
- Rational root = rm.first - q1half;
- rmMap.insert(std::make_pair((Real)root, rm.second));
- }
- }
- template <typename Rational>
- static void SolveCubic(Rational const& p0, Rational const& p1,
- Rational const& p2, Rational const& p3, std::map<Real, int>& rmMap)
- {
- Rational const rat2 = 2, rat3 = 3;
- Rational q0 = p0 / p3;
- Rational q1 = p1 / p3;
- Rational q2 = p2 / p3;
- Rational q2third = q2 / rat3;
- Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
- Rational c1 = q1 - q2 * q2third;
- std::map<Rational, int> rmLocalMap;
- SolveDepressedCubic(c0, c1, rmLocalMap);
- rmMap.clear();
- for (auto& rm : rmLocalMap)
- {
- Rational root = rm.first - q2third;
- rmMap.insert(std::make_pair((Real)root, rm.second));
- }
- }
- template <typename Rational>
- static void SolveQuartic(Rational const& p0, Rational const& p1,
- Rational const& p2, Rational const& p3, Rational const& p4,
- std::map<Real, int>& rmMap)
- {
- Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
- Rational q0 = p0 / p4;
- Rational q1 = p1 / p4;
- Rational q2 = p2 / p4;
- Rational q3 = p3 / p4;
- Rational q3fourth = q3 / rat4;
- Rational q3fourthSqr = q3fourth * q3fourth;
- Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
- Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
- Rational c2 = q2 - rat6 * q3fourthSqr;
- std::map<Rational, int> rmLocalMap;
- SolveDepressedQuartic(c0, c1, c2, rmLocalMap);
- rmMap.clear();
- for (auto& rm : rmLocalMap)
- {
- Rational root = rm.first - q3fourth;
- rmMap.insert(std::make_pair((Real)root, rm.second));
- }
- }
-
-
-
- template <typename Rational>
- static void GetRootInfoQuadratic(Rational const& p0, Rational const& p1,
- Rational const& p2, std::vector<int>& info)
- {
- Rational const rat2 = 2;
- Rational q0 = p0 / p2;
- Rational q1 = p1 / p2;
- Rational q1half = q1 / rat2;
- Rational c0 = q0 - q1half * q1half;
- info.clear();
- info.reserve(2);
- GetRootInfoDepressedQuadratic(c0, info);
- }
- template <typename Rational>
- static void GetRootInfoCubic(Rational const& p0, Rational const& p1,
- Rational const& p2, Rational const& p3, std::vector<int>& info)
- {
- Rational const rat2 = 2, rat3 = 3;
- Rational q0 = p0 / p3;
- Rational q1 = p1 / p3;
- Rational q2 = p2 / p3;
- Rational q2third = q2 / rat3;
- Rational c0 = q0 - q2third * (q1 - rat2 * q2third * q2third);
- Rational c1 = q1 - q2 * q2third;
- info.clear();
- info.reserve(3);
- GetRootInfoDepressedCubic(c0, c1, info);
- }
- template <typename Rational>
- static void GetRootInfoQuartic(Rational const& p0, Rational const& p1,
- Rational const& p2, Rational const& p3, Rational const& p4,
- std::vector<int>& info)
- {
- Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat6 = 6;
- Rational q0 = p0 / p4;
- Rational q1 = p1 / p4;
- Rational q2 = p2 / p4;
- Rational q3 = p3 / p4;
- Rational q3fourth = q3 / rat4;
- Rational q3fourthSqr = q3fourth * q3fourth;
- Rational c0 = q0 - q3fourth * (q1 - q3fourth * (q2 - q3fourthSqr * rat3));
- Rational c1 = q1 - rat2 * q3fourth * (q2 - rat4 * q3fourthSqr);
- Rational c2 = q2 - rat6 * q3fourthSqr;
- info.clear();
- info.reserve(4);
- GetRootInfoDepressedQuartic(c0, c1, c2, info);
- }
-
-
-
-
- static int Find(int degree, Real const* c, unsigned int maxIterations, Real* roots)
- {
- if (degree >= 0 && c)
- {
- Real const zero = (Real)0;
- while (degree >= 0 && c[degree] == zero)
- {
- --degree;
- }
- if (degree > 0)
- {
-
- Real const one = (Real)1;
- Real invLeading = one / c[degree];
- Real maxValue = zero;
- for (int i = 0; i < degree; ++i)
- {
- Real value = std::fabs(c[i] * invLeading);
- if (value > maxValue)
- {
- maxValue = value;
- }
- }
- Real bound = one + maxValue;
- return FindRecursive(degree, c, -bound, bound, maxIterations,
- roots);
- }
- else if (degree == 0)
- {
-
- return 0;
- }
- else
- {
-
- roots[0] = zero;
- return 1;
- }
- }
- else
- {
-
- return 0;
- }
- }
-
-
- static bool Find(int degree, Real const* c, Real tmin, Real tmax,
- unsigned int maxIterations, Real& root)
- {
- Real const zero = (Real)0;
- Real pmin = Evaluate(degree, c, tmin);
- if (pmin == zero)
- {
- root = tmin;
- return true;
- }
- Real pmax = Evaluate(degree, c, tmax);
- if (pmax == zero)
- {
- root = tmax;
- return true;
- }
- if (pmin * pmax > zero)
- {
-
- return false;
- }
- if (tmin >= tmax)
- {
-
- return false;
- }
- for (unsigned int i = 1; i <= maxIterations; ++i)
- {
- root = ((Real)0.5) * (tmin + tmax);
-
-
- if (root == tmin || root == tmax)
- {
- break;
- }
- Real p = Evaluate(degree, c, root);
- Real product = p * pmin;
- if (product < zero)
- {
- tmax = root;
- pmax = p;
- }
- else if (product > zero)
- {
- tmin = root;
- pmin = p;
- }
- else
- {
- break;
- }
- }
- return true;
- }
- private:
-
- template <typename Rational>
- static void SolveDepressedQuadratic(Rational const& c0,
- std::map<Rational, int>& rmMap)
- {
- Rational const zero = 0;
- if (c0 < zero)
- {
-
- Rational root1 = (Rational)std::sqrt((double)-c0);
- Rational root0 = -root1;
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(0);
- }
- else if (c0 == zero)
- {
-
- rmMap.insert(std::make_pair(zero, 2));
- GTE_ROOTS_LOW_DEGREE_BLOCK(1);
- }
- else
- {
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(2);
- }
- }
- template <typename Rational>
- static void SolveDepressedCubic(Rational const& c0, Rational const& c1,
- std::map<Rational, int>& rmMap)
- {
-
-
- Rational const zero = 0;
- if (c0 == zero)
- {
- SolveDepressedQuadratic(c1, rmMap);
- auto iter = rmMap.find(zero);
- if (iter != rmMap.end())
- {
-
-
- ++iter->second;
- GTE_ROOTS_LOW_DEGREE_BLOCK(3);
- }
- else
- {
-
-
- rmMap.insert(std::make_pair(zero, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(4);
- }
- return;
- }
-
- double const oneThird = 1.0 / 3.0;
- if (c1 == zero)
- {
-
- Rational root0;
- if (c0 > zero)
- {
- root0 = (Rational)-std::pow((double)c0, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(5);
- }
- else
- {
- root0 = (Rational)std::pow(-(double)c0, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(6);
- }
- rmMap.insert(std::make_pair(root0, 1));
-
-
-
- return;
- }
-
- Rational const rat2 = 2, rat3 = 3, rat4 = 4, rat27 = 27, rat108 = 108;
- Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
- if (delta > zero)
- {
-
- Rational deltaDiv108 = delta / rat108;
- Rational betaRe = -c0 / rat2;
- Rational betaIm = std::sqrt(deltaDiv108);
- Rational theta = std::atan2(betaIm, betaRe);
- Rational thetaDiv3 = theta / rat3;
- double angle = (double)thetaDiv3;
- Rational cs = (Rational)std::cos(angle);
- Rational sn = (Rational)std::sin(angle);
- Rational rhoSqr = betaRe * betaRe + betaIm * betaIm;
- Rational rhoPowThird = (Rational)std::pow((double)rhoSqr, 1.0 / 6.0);
- Rational temp0 = rhoPowThird * cs;
- Rational temp1 = rhoPowThird * sn * (Rational)std::sqrt(3.0);
- Rational root0 = rat2 * temp0;
- Rational root1 = -temp0 - temp1;
- Rational root2 = -temp0 + temp1;
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
- rmMap.insert(std::make_pair(root2, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(7);
- }
- else if (delta < zero)
- {
-
- Rational deltaDiv108 = delta / rat108;
- Rational temp0 = -c0 / rat2;
- Rational temp1 = (Rational)std::sqrt(-(double)deltaDiv108);
- Rational temp2 = temp0 - temp1;
- Rational temp3 = temp0 + temp1;
- if (temp2 >= zero)
- {
- temp2 = (Rational)std::pow((double)temp2, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(8);
- }
- else
- {
- temp2 = (Rational)-std::pow(-(double)temp2, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(9);
- }
- if (temp3 >= zero)
- {
- temp3 = (Rational)std::pow((double)temp3, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(10);
- }
- else
- {
- temp3 = (Rational)-std::pow(-(double)temp3, oneThird);
- GTE_ROOTS_LOW_DEGREE_BLOCK(11);
- }
- Rational root0 = temp2 + temp3;
- rmMap.insert(std::make_pair(root0, 1));
-
-
-
- }
- else
- {
-
- Rational root0 = -rat3 * c0 / (rat2 * c1);
- Rational root1 = -rat2 * root0;
- rmMap.insert(std::make_pair(root0, 2));
- rmMap.insert(std::make_pair(root1, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(12);
- }
- }
- template <typename Rational>
- static void SolveDepressedQuartic(Rational const& c0, Rational const& c1,
- Rational const& c2, std::map<Rational, int>& rmMap)
- {
-
-
- Rational const zero = 0;
- if (c0 == zero)
- {
- SolveDepressedCubic(c1, c2, rmMap);
- auto iter = rmMap.find(zero);
- if (iter != rmMap.end())
- {
-
-
- ++iter->second;
- GTE_ROOTS_LOW_DEGREE_BLOCK(13);
- }
- else
- {
-
-
- rmMap.insert(std::make_pair(zero, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(14);
- }
- return;
- }
-
-
-
- if (c1 == zero)
- {
- SolveBiquadratic(c0, c2, rmMap);
- return;
- }
-
-
-
- Rational const rat2 = 2, rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
- Rational const rat27 = 27, rat36 = 36;
- Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
- Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
- (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
- rat16 * c0sqr);
- Rational a0 = rat12 * c0 + c2sqr;
- Rational a1 = rat4 * c0 - c2sqr;
- if (delta > zero)
- {
- if (c2 < zero && a1 < zero)
- {
-
- std::map<Real, int> rmCubicMap;
- SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8, rmCubicMap);
- Rational t = (Rational)rmCubicMap.rbegin()->first;
- Rational alphaSqr = rat2 * t - c2;
- Rational alpha = (Rational)std::sqrt((double)alphaSqr);
- double sgnC1;
- if (c1 > zero)
- {
- sgnC1 = 1.0;
- GTE_ROOTS_LOW_DEGREE_BLOCK(15);
- }
- else
- {
- sgnC1 = -1.0;
- GTE_ROOTS_LOW_DEGREE_BLOCK(16);
- }
- Rational arg = t * t - c0;
- Rational beta = (Rational)(sgnC1 * std::sqrt(std::max((double)arg, 0.0)));
- Rational D0 = alphaSqr - rat4 * (t + beta);
- Rational sqrtD0 = (Rational)std::sqrt(std::max((double)D0, 0.0));
- Rational D1 = alphaSqr - rat4 * (t - beta);
- Rational sqrtD1 = (Rational)std::sqrt(std::max((double)D1, 0.0));
- Rational root0 = (alpha - sqrtD0) / rat2;
- Rational root1 = (alpha + sqrtD0) / rat2;
- Rational root2 = (-alpha - sqrtD1) / rat2;
- Rational root3 = (-alpha + sqrtD1) / rat2;
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
- rmMap.insert(std::make_pair(root2, 1));
- rmMap.insert(std::make_pair(root3, 1));
- }
- else
- {
-
-
-
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(17);
- }
- }
- else if (delta < zero)
- {
-
- std::map<Real, int> rmCubicMap;
- SolveCubic(c1sqr - rat4 * c0 * c2, rat8 * c0, rat4 * c2, -rat8,
- rmCubicMap);
- Rational t = (Rational)rmCubicMap.rbegin()->first;
- Rational alphaSqr = rat2 * t - c2;
- Rational alpha = (Rational)std::sqrt(std::max((double)alphaSqr, 0.0));
- double sgnC1;
- if (c1 > zero)
- {
- sgnC1 = 1.0;
- }
- else
- {
- sgnC1 = -1.0;
- }
- Rational arg = t * t - c0;
- Rational beta = (Rational)(sgnC1 * std::sqrt(std::max((double)arg, 0.0)));
- Rational root0, root1;
- if (sgnC1 > 0.0)
- {
- Rational D1 = alphaSqr - rat4 * (t - beta);
- Rational sqrtD1 = (Rational)std::sqrt(std::max((double)D1, 0.0));
- root0 = (-alpha - sqrtD1) / rat2;
- root1 = (-alpha + sqrtD1) / rat2;
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(18);
- }
- else
- {
- Rational D0 = alphaSqr - rat4 * (t + beta);
- Rational sqrtD0 = (Rational)std::sqrt(std::max((double)D0, 0.0));
- root0 = (alpha - sqrtD0) / rat2;
- root1 = (alpha + sqrtD0) / rat2;
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(19);
- }
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
- }
- else
- {
- if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
- {
-
- Rational const rat9 = 9;
- Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
- rmMap.insert(std::make_pair(root0, 2));
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(20);
- }
- else
- {
- Rational const rat3 = 3;
- if (a0 != zero)
- {
-
- Rational const rat9 = 9;
- Rational root0 = -c1 * a0 / (rat9 * c1sqr - rat2 * c2 * a1);
- Rational alpha = rat2 * root0;
- Rational beta = c2 + rat3 * root0 * root0;
- Rational discr = alpha * alpha - rat4 * beta;
- Rational temp1 = (Rational)std::sqrt((double)discr);
- Rational root1 = (-alpha - temp1) / rat2;
- Rational root2 = (-alpha + temp1) / rat2;
- rmMap.insert(std::make_pair(root0, 2));
- rmMap.insert(std::make_pair(root1, 1));
- rmMap.insert(std::make_pair(root2, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(21);
- }
- else
- {
-
- Rational root0 = -rat3 * c1 / (rat4 * c2);
- Rational root1 = -rat3 * root0;
- rmMap.insert(std::make_pair(root0, 3));
- rmMap.insert(std::make_pair(root1, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(22);
- }
- }
- }
- }
- template <typename Rational>
- static void SolveBiquadratic(Rational const& c0, Rational const& c2,
- std::map<Rational, int>& rmMap)
- {
-
-
-
-
- Rational const zero = 0, rat2 = 2, rat256 = 256;
- Rational c2Half = c2 / rat2;
- Rational a1 = c0 - c2Half * c2Half;
- Rational delta = rat256 * c0 * a1 * a1;
- if (delta > zero)
- {
- if (c2 < zero)
- {
- if (a1 < zero)
- {
-
- Rational temp0 = (Rational)std::sqrt(-(double)a1);
- Rational temp1 = -c2Half - temp0;
- Rational temp2 = -c2Half + temp0;
- Rational root1 = (Rational)std::sqrt((double)temp1);
- Rational root0 = -root1;
- Rational root2 = (Rational)std::sqrt((double)temp2);
- Rational root3 = -root2;
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
- rmMap.insert(std::make_pair(root2, 1));
- rmMap.insert(std::make_pair(root3, 1));
- GTE_ROOTS_LOW_DEGREE_BLOCK(23);
- }
- else
- {
-
-
-
-
-
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(24);
- }
- }
- else
- {
-
-
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(25);
- }
- }
- else if (delta < zero)
- {
-
- Rational temp0 = (Rational)std::sqrt(-(double)a1);
- Rational temp1 = -c2Half + temp0;
- Rational root1 = (Rational)std::sqrt((double)temp1);
- Rational root0 = -root1;
- rmMap.insert(std::make_pair(root0, 1));
- rmMap.insert(std::make_pair(root1, 1));
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(26);
- }
- else
- {
- if (c2 < zero)
- {
-
- Rational root1 = (Rational)std::sqrt(-(double)c2Half);
- Rational root0 = -root1;
- rmMap.insert(std::make_pair(root0, 2));
- rmMap.insert(std::make_pair(root1, 2));
- GTE_ROOTS_LOW_DEGREE_BLOCK(27);
- }
- else
- {
-
-
-
- GTE_ROOTS_LOW_DEGREE_BLOCK(28);
- }
- }
- }
-
- template <typename Rational>
- static void GetRootInfoDepressedQuadratic(Rational const& c0,
- std::vector<int>& info)
- {
- Rational const zero = 0;
- if (c0 < zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- }
- else if (c0 == zero)
- {
-
- info.push_back(2);
- }
- else
- {
-
- }
- }
- template <typename Rational>
- static void GetRootInfoDepressedCubic(Rational const& c0,
- Rational const& c1, std::vector<int>& info)
- {
-
-
- Rational const zero = 0;
- if (c0 == zero)
- {
- if (c1 == zero)
- {
- info.push_back(3);
- }
- else
- {
- info.push_back(1);
- GetRootInfoDepressedQuadratic(c1, info);
- }
- return;
- }
- Rational const rat4 = 4, rat27 = 27;
- Rational delta = -(rat4 * c1 * c1 * c1 + rat27 * c0 * c0);
- if (delta > zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- info.push_back(1);
- }
- else if (delta < zero)
- {
-
- info.push_back(1);
- }
- else
- {
-
- info.push_back(1);
- info.push_back(2);
- }
- }
- template <typename Rational>
- static void GetRootInfoDepressedQuartic(Rational const& c0,
- Rational const& c1, Rational const& c2, std::vector<int>& info)
- {
-
-
- Rational const zero = 0;
- if (c0 == zero)
- {
- if (c1 == zero)
- {
- if (c2 == zero)
- {
- info.push_back(4);
- }
- else
- {
- info.push_back(2);
- GetRootInfoDepressedQuadratic(c2, info);
- }
- }
- else
- {
- info.push_back(1);
- GetRootInfoDepressedCubic(c1, c2, info);
- }
- return;
- }
-
-
-
- if (c1 == zero)
- {
- GetRootInfoBiquadratic(c0, c2, info);
- return;
- }
-
-
-
- Rational const rat4 = 4, rat8 = 8, rat12 = 12, rat16 = 16;
- Rational const rat27 = 27, rat36 = 36;
- Rational c0sqr = c0 * c0, c1sqr = c1 * c1, c2sqr = c2 * c2;
- Rational delta = c1sqr * (-rat27 * c1sqr + rat4 * c2 *
- (rat36 * c0 - c2sqr)) + rat16 * c0 * (c2sqr * (c2sqr - rat8 * c0) +
- rat16 * c0sqr);
- Rational a0 = rat12 * c0 + c2sqr;
- Rational a1 = rat4 * c0 - c2sqr;
- if (delta > zero)
- {
- if (c2 < zero && a1 < zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- info.push_back(1);
- info.push_back(1);
- }
- else
- {
-
- }
- }
- else if (delta < zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- }
- else
- {
- if (a1 > zero || (c2 > zero && (a1 != zero || c1 != zero)))
- {
-
- info.push_back(2);
- }
- else
- {
- if (a0 != zero)
- {
-
- info.push_back(2);
- info.push_back(1);
- info.push_back(1);
- }
- else
- {
-
- info.push_back(3);
- info.push_back(1);
- }
- }
- }
- }
- template <typename Rational>
- static void GetRootInfoBiquadratic(Rational const& c0,
- Rational const& c2, std::vector<int>& info)
- {
-
-
-
-
- Rational const zero = 0, rat2 = 2, rat256 = 256;
- Rational c2Half = c2 / rat2;
- Rational a1 = c0 - c2Half * c2Half;
- Rational delta = rat256 * c0 * a1 * a1;
- if (delta > zero)
- {
- if (c2 < zero)
- {
- if (a1 < zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- info.push_back(1);
- info.push_back(1);
- }
- else
- {
-
- }
- }
- else
- {
-
- }
- }
- else if (delta < zero)
- {
-
- info.push_back(1);
- info.push_back(1);
- }
- else
- {
- if (c2 < zero)
- {
-
- info.push_back(2);
- info.push_back(2);
- }
- else
- {
-
- }
- }
- }
-
- static int FindRecursive(int degree, Real const* c, Real tmin, Real tmax,
- unsigned int maxIterations, Real* roots)
- {
-
- Real const zero = (Real)0;
- Real root = zero;
- if (degree == 1)
- {
- int numRoots;
- if (c[1] != zero)
- {
- root = -c[0] / c[1];
- numRoots = 1;
- }
- else if (c[0] == zero)
- {
- root = zero;
- numRoots = 1;
- }
- else
- {
- numRoots = 0;
- }
- if (numRoots > 0 && tmin <= root && root <= tmax)
- {
- roots[0] = root;
- return 1;
- }
- return 0;
- }
-
-
-
-
-
-
- int derivDegree = degree - 1;
- std::vector<Real> derivCoeff(derivDegree + 1);
- std::vector<Real> derivRoots(derivDegree);
- for (int i = 0; i <= derivDegree; ++i)
- {
- derivCoeff[i] = c[i + 1] * (Real)(i + 1) / (Real)degree;
- }
- int numDerivRoots = FindRecursive(degree - 1, &derivCoeff[0], tmin, tmax,
- maxIterations, &derivRoots[0]);
- int numRoots = 0;
- if (numDerivRoots > 0)
- {
-
- if (Find(degree, c, tmin, derivRoots[0], maxIterations, root))
- {
- roots[numRoots++] = root;
- }
-
- for (int i = 0; i <= numDerivRoots - 2; ++i)
- {
- if (Find(degree, c, derivRoots[i], derivRoots[i + 1],
- maxIterations, root))
- {
- roots[numRoots++] = root;
- }
- }
-
- if (Find(degree, c, derivRoots[numDerivRoots - 1], tmax,
- maxIterations, root))
- {
- roots[numRoots++] = root;
- }
- }
- else
- {
-
- if (Find(degree, c, tmin, tmax, maxIterations, root))
- {
- roots[numRoots++] = root;
- }
- }
- return numRoots;
- }
- static Real Evaluate(int degree, Real const* c, Real t)
- {
- int i = degree;
- Real result = c[i];
- while (--i >= 0)
- {
- result = t * result + c[i];
- }
- return result;
- }
- };
- }
|