#ifndef polynomial_h #define polynomial_h #pragma once template class polynomial_tpl { public: explicit polynomial_tpl() { denom=(ftype)1; }; explicit polynomial_tpl(ftype op) { zero(); data[degree]=op; } polynomial_tpl& zero() { for(int i=0;i<=degree;i++) data[i]=0; denom=(ftype)1; return *this; } polynomial_tpl(const polynomial_tpl& src) { *this=src; } polynomial_tpl& operator=(const polynomial_tpl &src) { denom=src.denom; for(int i=0;i<=degree;i++) data[i]=src.data[i]; return *this; } template polynomial_tpl& operator=(const polynomial_tpl &src) { int i; denom = src.denom; for(i=0;i<=min(degree,degree1);i++) data[i] = src.data[i]; for(;i &deriv,int curdegree=degree) const; polynomial_tpl& fixsign() { ftype sg = sgnnz(denom); denom *= sg; for(int i=0;i<=degree;i++) data[i]*=sg; return *this; } int findroots(ftype start,ftype end, ftype *proots, int nIters=20,int curdegree=degree) const; int nroots(ftype start,ftype end) const; ftype eval(ftype x) const { ftype res=0; for(int i=degree;i>=0;i--) res = res*x+data[i]; return res; } ftype eval(ftype x,int subdegree) const { ftype res = data[subdegree]; for(int i=subdegree-1;i>=0;i--) res = res*x+data[i]; return res; } polynomial_tpl& operator+=(ftype op) { data[0] += op*denom; return *this; } polynomial_tpl& operator-=(ftype op) { data[0] -= op*denom; return *this; } polynomial_tpl operator*(ftype op) const { polynomial_tpl res; res.denom = denom; for(int i=0;i<=degree;i++) res.data[i] = data[i]*op; return res; } polynomial_tpl& operator*=(ftype op) { for(int i=0;i<=degree;i++) data[i]*=op; return *this; } polynomial_tpl operator/(ftype op) const { polynomial_tpl res = *this; res.denom = denom*op; return res; } polynomial_tpl& operator/=(ftype op) { denom *= op; return *this; } polynomial_tpl sqr() const { return *this**this; } ftype denom; ftype data[degree+1]; }; template struct tagPolyE { inline static ftype polye() {return (ftype)1E-10;} }; inline float tagPolyE::polye() {return 1e-6f;} template inline ftype polye() { return tagPolyE::polye(); } #define degmax(degree1,degree2) degree1-(degree1-degree2&(degree1-degree2)>>31) template polynomial_tpl operator+(const polynomial_tpl &pn, ftype op) { polynomial_tpl res = pn; res.data[0] += op*res.denom; return res; } template polynomial_tpl operator-(const polynomial_tpl &pn, ftype op) { polynomial_tpl res = pn; res.data[0] -= op*res.denom; return res; } template polynomial_tpl operator+(ftype op, const polynomial_tpl &pn) { polynomial_tpl res = pn; res.data[0] += op*res.denom; return res; } template polynomial_tpl operator-(ftype op, const polynomial_tpl &pn) { polynomial_tpl res = pn; res.data[0] -= op*res.denom; for(int i=0;i<=degree;i++) res.data[i]=-res.data[i]; return res; } template polynomial_tpl psqr(const polynomial_tpl &op) { return op*op; } template polynomial_tpl operator+(const polynomial_tpl &op1, const polynomial_tpl &op2) { polynomial_tpl res; int i; for(i=0;i<=min(degree1,degree2);i++) res.data[i] = op1.data[i]*op2.denom+op2.data[i]*op1.denom; for(;i<=degree1;i++) res.data[i] = op1.data[i]*op2.denom; for(;i<=degree2;i++) res.data[i] = op2.data[i]*op1.denom; res.denom = op1.denom*op2.denom; return res; } template polynomial_tpl operator-(const polynomial_tpl &op1, const polynomial_tpl &op2) { polynomial_tpl res; int i; for(i=0;i<=min(degree1,degree2);i++) res.data[i] = op1.data[i]*op2.denom-op2.data[i]*op1.denom; for(;i<=degree1;i++) res.data[i] = op1.data[i]*op2.denom; for(;i<=degree2;i++) res.data[i] = op2.data[i]*op1.denom; res.denom = op1.denom*op2.denom; return res; } template polynomial_tpl& operator+=(polynomial_tpl &op1, const polynomial_tpl &op2) { for(int i=0;i polynomial_tpl& operator-=(polynomial_tpl &op1, const polynomial_tpl &op2) { for(int i=0;i polynomial_tpl operator*(const polynomial_tpl &op1, const polynomial_tpl &op2) { polynomial_tpl res; res.zero(); int j; switch (degree1) { case 8: for(j=0;j<=degree2;j++) res.data[8+j] += op1.data[8]*op2.data[j]; case 7: for(j=0;j<=degree2;j++) res.data[7+j] += op1.data[7]*op2.data[j]; case 6: for(j=0;j<=degree2;j++) res.data[6+j] += op1.data[6]*op2.data[j]; case 5: for(j=0;j<=degree2;j++) res.data[5+j] += op1.data[5]*op2.data[j]; case 4: for(j=0;j<=degree2;j++) res.data[4+j] += op1.data[4]*op2.data[j]; case 3: for(j=0;j<=degree2;j++) res.data[3+j] += op1.data[3]*op2.data[j]; case 2: for(j=0;j<=degree2;j++) res.data[2+j] += op1.data[2]*op2.data[j]; case 1: for(j=0;j<=degree2;j++) res.data[1+j] += op1.data[1]*op2.data[j]; case 0: for(j=0;j<=degree2;j++) res.data[0+j] += op1.data[0]*op2.data[j]; } res.denom = op1.denom*op2.denom; return res; } template void polynomial_divide(const polynomial_tpl &num, const polynomial_tpl &den, polynomial_tpl ", polynomial_tpl &rem, int degree1,int degree2) { int i,j,k,l; ftype maxel; for(i=0;i<=degree1;i++) rem.data[i] = num.data[i]; for(i=0;i<=degree1-degree2;i++) quot.data[i] = 0; for(i=1,maxel=fabs_tpl(num.data[0]); i<=degree1; i++) maxel = max(maxel,num.data[i]); for(maxel*=polye(); degree1>=0 && fabs_tpl(num.data[degree1])(); degree2>=0 && fabs_tpl(den.data[degree2])=degree2; l--,k--) { quot.data[k] = rem.data[l]*den.denom; quot.denom *= den.data[degree2]; for(i=degree1-degree2; i>k; i--) quot.data[i] *= den.data[degree2]; for(i=degree2-1,j=l-1; i>=0; i--,j--) rem.data[j] = rem.data[j]*den.data[degree2] - den.data[i]*rem.data[l]; for(; j>=0; j--) rem.data[j] *= den.data[degree2]; rem.denom *= den.data[degree2]; } } template polynomial_tpl operator/(const polynomial_tpl &num, const polynomial_tpl &den) { polynomial_tpl quot; polynomial_tpl rem; polynomial_divide((polynomial_tpl&)num,(polynomial_tpl&)den, (polynomial_tpl&)quot, (polynomial_tpl&)rem, degree1,degree2); return quot; } template polynomial_tpl operator%(const polynomial_tpl &num, const polynomial_tpl &den) { polynomial_tpl quot; polynomial_tpl rem; polynomial_divide((polynomial_tpl&)num,(polynomial_tpl&)den, (polynomial_tpl&)quot, (polynomial_tpl&)rem, degree1,degree2); return (polynomial_tpl&)rem; } template void polynomial_tpl::calc_deriviative(polynomial_tpl &deriv, int curdegree) const { for(int i=0; i int polynomial_tpl::nroots(ftype start,ftype end) const { polynomial_tpl f[degree+1]; int i,j,sg_a,sg_b; ftype val,prevval; calc_deriviative(f[0]); polynomial_divide((polynomial_tpl&)*this,(polynomial_tpl&)f[0], (polynomial_tpl&)f[degree], (polynomial_tpl&)f[1], degree,degree-1); f[1].denom = -f[1].denom; for(i=2;i&)f[i-2],(polynomial_tpl&)f[i-1], (polynomial_tpl&)f[degree], (polynomial_tpl&)f[i], degree+1-i,degree-i); f[i].denom = -f[i].denom; if (fabs_tpl(f[i].denom)>(ftype)1E10) { for(j=0;j<=degree-1-i;j++) f[i].data[j] *= (ftype)1E-10; f[i].denom *= (ftype)1E-10; } } prevval = eval(start)*denom; for(i=sg_a=0; i inline ftype cubert_tpl(ftype x) { return fabs_tpl(x)>1E-20 ? exp_tpl(log_tpl(fabs_tpl(x))*(ftype)(1.0/3))*sgnnz(x) : x; } template inline ftype pow_tpl(ftype x,ftype pow) { return fabs_tpl(x)>1E-20 ? exp_tpl(log_tpl(fabs_tpl(x))*pow)*sgnnz(x) : x; } template inline void swap(ftype *ptr,int i,int j) { ftype t=ptr[i]; ptr[i]=ptr[j]; ptr[j]=t; } template int polynomial_tpl::findroots(ftype start,ftype end, ftype *proots,int nIters,int degree) const { int i,j,nRoots=0; ftype maxel; for(i=1,maxel=fabs_tpl(data[0]); i<=degree; i++) maxel = max(maxel,data[i]); for(maxel*=polye(); degree>0 && fabs_tpl(data[degree])0) { proots[0] = cubert_tpl(q+Qr)+cubert_tpl(q-Qr) - a3; nRoots = 1; } else { phi = atan2_tpl(Qr,q)*(ftype)(1.0/3); t = pow_tpl(Qr*Qr+q*q,(ftype)(1.0/6)); Ar = t*cos_tpl(phi); Ai = t*sin_tpl(phi); proots[0] = 2*Ar - a3; proots[1] = -Ar + Ai*sqrt3 - a3; proots[2] = -Ar - Ai*sqrt3 - a3; i = idxmax3(proots); swap(proots,i,2); i = isneg(proots[0]-proots[1]); swap(proots,i,1); nRoots = 3; } } else if (degree==4) { ftype t,a3,a2,a1,a0,y,R,D,E,subroots[3]; const ftype e = 1E-9; t=(ftype)1.0/data[4]; a3=data[3]*t; a2=data[2]*t; a1=data[1]*t; a0=data[0]*t; polynomial_tpl p3aux; ftype kp3aux[]={ 1, -a2, a1*a3-4*a0, 4*a2*a0-a1*a1-a3*a3*a0 }; p3aux.set(kp3aux); p3aux.findroots(-1E10,1E10,subroots); y=subroots[0]; R = a3*a3*(ftype)0.25-a2+y; if (R>-e) { if (R-e) { D = sqrt_tpl(max((ftype)0,D+t)); proots[nRoots++] = a3*(ftype)-0.25+(R-D)*(ftype)0.5; proots[nRoots++] = a3*(ftype)-0.25+(R+D)*(ftype)0.5; } if (E-t>-e) { E = sqrt_tpl(max((ftype)0,E-t)); proots[nRoots++] = a3*(ftype)-0.25-(R+E)*(ftype)0.5; proots[nRoots++] = a3*(ftype)-0.25-(R-E)*(ftype)0.5; } if (nRoots==4) { i = idxmax3(proots); if (proots[3]4) { ftype roots[maxdegree+1],prevroot,val,prevval[2],curval,bound[2],middle; polynomial_tpl deriv; int nExtremes,iter,iBound; calc_deriviative(deriv); // find a subset of deriviative extremes between start and end for(nExtremes=deriv.findroots(start,end,roots+1,nIters,degree-1)+1; nExtremes>1 && roots[nExtremes-1]>end; nExtremes--); for(i=1;ii && proots[nRoots-1]>end;nRoots--); for(j=i;j P2; typedef polynomial_tpl P1; typedef polynomial_tpl P2f; typedef polynomial_tpl P1f; #endif