11#include <gsl/gsl_poly.h>
33 : iDegree((iD > 0) ? iD : 0), afCoeff(iDegree + 1), Eaccuracy(1e-6)
41 : iDegree((iD > 0) ? iD : 0), afCoeff(iDegree + 1), Eaccuracy(
fabs(E))
68PolyBase::operator
const std::vector<double> &()
const
77PolyBase::operator std::vector<double> &()
93 if (i > iDegree || i < 0)
117 double Result = afCoeff[iDegree];
118 for (
int i = iDegree - 1; i >= 0; i--) {
120 Result += afCoeff[i];
161 std::vector<double> CX(iD + 1, 0.0);
162 for (
int i = 0; i <=
iDegree; i++)
163 for (
int j = 0; j <= A.
iDegree; j++) {
164 const int cIndex = i + j;
279 using std::placeholders::_1;
280 transform(
afCoeff.begin(),
afCoeff.end(),
afCoeff.begin(), std::bind(std::multiplies<double>(), _1, V));
291 using std::placeholders::_1;
292 transform(
afCoeff.begin(),
afCoeff.end(),
afCoeff.begin(), std::bind(std::divides<double>(), _1, V));
328 for (
int i = 0; i <
iDegree; i++)
342 for (
int i = 0; i <=
iDegree; i++)
355 const double eps((epsilon > 0.0) ? epsilon :
Eaccuracy);
362 for (
int i = 0; i <
iDegree; i++)
387 const int iQuotDegree = iDegree - pD.iDegree;
388 if (iQuotDegree >= 0) {
389 pQ.setDegree(iQuotDegree);
394 double fInv = 1.0 / pD[pD.iDegree];
395 for (
int iQ = iQuotDegree; iQ >= 0; iQ--) {
396 int iR = pD.iDegree + iQ;
397 pQ[iQ] = fInv * pR[iR];
398 for (iR--; iR >= iQ; iR--)
399 pR.afCoeff[iR] -= pQ[iQ] * pD[iR - iQ];
403 pR.compress(epsilon);
419 const double eps((epsilon > 0.0) ? epsilon :
Eaccuracy);
420 std::vector<std::complex<double>> Croots =
calcRoots(epsilon);
421 std::vector<double> Out;
422 std::vector<std::complex<double>>::const_iterator vc;
423 for (vc = Croots.begin(); vc != Croots.end(); ++vc) {
424 if (
fabs(vc->imag()) < eps)
425 Out.emplace_back(vc->real());
444 std::vector<std::complex<double>> Out(
iDegree);
451 Out[0] = std::complex<double>(-
afCoeff[0]);
468 gsl_poly_complex_workspace *WS(gsl_poly_complex_workspace_alloc(
iDegree + 1));
469 auto RZ =
new double[2 * (
iDegree + 1)];
471 for (
int i = 0; i <
iDegree; i++)
472 Out[i] = std::complex<double>(RZ[2 * i], RZ[2 * i + 1]);
473 gsl_poly_complex_workspace_free(WS);
487 const double b = afCoeff[1];
488 const double c = afCoeff[0];
490 const double cf = b * b - 4.0 * c;
493 const double q = (b >= 0) ? -0.5 * (b + sqrt(cf)) : -0.5 * (b - sqrt(cf));
494 AnsA = std::complex<double>(q, 0.0);
495 AnsB = std::complex<double>(c / q, 0.0);
496 return (cf == 0) ? 1 : 2;
499 std::complex<double> CQ(-0.5 * b, (b >= 0 ? -0.5 * sqrt(-cf) : 0.5 * sqrt(-cf)));
505int PolyBase::solveCubic(std::complex<double> &AnsA, std::complex<double> &AnsB, std::complex<double> &AnsC)
const
517 double termR, discrim;
521 const double b = afCoeff[2];
522 const double c = afCoeff[1];
523 const double d = afCoeff[0];
525 q = (3.0 * c - (b * b)) / 9.0;
526 r = -27.0 *
d + b * (9.0 * c - 2.0 * b * b);
529 discrim = q * q * q + r * r;
536 s = r + sqrt(discrim);
537 s = ((s < 0) ? -pow(-s, (1.0 / 3.0)) : pow(s, (1.0 / 3.0)));
538 t = r - sqrt(discrim);
539 t = ((t < 0) ? -pow(-t, (1.0 / 3.0)) : pow(t, (1.0 / 3.0)));
540 AnsA = std::complex<double>(-termR + s + t, 0.0);
542 termR += (s + t) / 2.0;
543 termI = sqrt(3.0) * (-t + s) / 2;
544 AnsB = std::complex<double>(-termR, termI);
545 AnsC = std::complex<double>(-termR, -termI);
556 q3 = acos(-r / sqrt(q3));
557 r13 = -2.0 * sqrt(q);
558 AnsA = std::complex<double>(-termR + r13 * cos(q3 / 3.0), 0.0);
559 AnsB = std::complex<double>(-termR + r13 * cos((q3 + 2.0 * M_PI) / 3.0), 0.0);
560 AnsC = std::complex<double>(-termR + r13 * cos((q3 - 2.0 * M_PI) / 3.0), 0.0);
567 r13 = ((r < 0) ? -pow(-r, (1.0 / 3.0)) : pow(r, (1.0 / 3.0)));
568 AnsA = std::complex<double>(-termR + 2.0 * r13, 0.0);
569 AnsB = std::complex<double>(-(r13 + termR), 0.0);
570 AnsC = std::complex<double>(-(r13 + termR), 0.0);
580 copy(afCoeff.begin(), afCoeff.end(), std::ostream_iterator<double>(OX,
" "));
Exception for index errors.
Holds a polynominal as a primary type.
PolyBase operator+(const PolyBase &) const
PolyBase addition.
void setDegree(int const)
Set the degree value.
int solveCubic(std::complex< double > &, std::complex< double > &, std::complex< double > &) const
Solves Cubic equation Compress MUST have been called.
std::vector< double > afCoeff
Coefficients.
double operator()(double const) const
Calculate polynomial at x.
PolyBase operator/(double const) const
PolyBase division.
double Eaccuracy
Polynomic accuracy.
PolyBase & derivative()
Take derivative of this polynomial.
int solveQuadratic(std::complex< double > &, std::complex< double > &) const
Solves Complex Quadratic component.
PolyBase GetInversion() const
Inversion of the coefficients.
PolyBase(int const)
Constructor.
void write(std::ostream &) const
Basic write command.
int iDegree
Degree of polynomial [0 == constant].
PolyBase & operator+=(const PolyBase &)
Self addition value.
PolyBase & operator-=(const PolyBase &)
Self addition value.
void divide(const PolyBase &, PolyBase &, PolyBase &, double const =-1.0) const
Carry out polynomial division of this / pD (Euclidean algorithm) If 'this' is P(t) and the divisor is...
PolyBase getDerivative() const
Take derivative.
int getDegree() const
Accessor to degree size.
std::vector< double > realRoots(double const =-1.0)
Get just the real roots.
double operator[](int const) const
Accessor to component.
PolyBase operator*(const PolyBase &) const
PolyBase multiplication.
PolyBase & operator/=(double const)
PolyBase division scalar.
PolyBase operator-() const
PolyBase negation operator.
PolyBase & operator*=(const PolyBase &)
Self multiplication value.
void compress(double const)
Two part process remove coefficients of zero or near zero: Reduce degree by eliminating all (nearly) ...
std::vector< std::complex< double > > calcRoots(double const =-1.0)
Calculate all the roots of the polynominal.
std::ostream & operator<<(std::ostream &, const PolyBase &)
External Friend :: outputs point to a stream.