1 #include "utilitaire_algebre.h"
7 roots_polynoms::roots_polynoms(): smalno(DBL_MIN), infin(DBL_MAX), //Parameters associated to the type double.
8 eta(DBL_EPSILON), base(FLT_RADIX)
12 int roots_polynoms::rpoly(double *op, int degree, double *zeror, double *zeroi)
14 double t,aa,bb,cc,*temp,factor,rot;
16 double lo,max,min,xx,yy,cosr,sinr,xxx,x,sc,bnd;
18 int cnt,nz,i,j,jj,l,nm1,zerok;
20 /* The following statements set machine constants. */
24 /* Initialization of constants for shift rotation. */
32 /* Algorithm fails of the leading coefficient is zero. */
33 if (fabs(op[0]) <= smalno) return -1;
34 /* Remove the zeros at the origin, if any. */
35 while (op[n] == 0.0) {
44 * Allocate memory here
46 temp = new double [degree+1];
47 pt = new double [degree+1];
48 p = new double [degree+1];
49 qp = new double [degree+1];
50 k = new double [degree+1];
51 qk = new double [degree+1];
52 svk = new double [degree+1];
53 /* Make a copy of the coefficients. */
56 /* Start the algorithm for one zero. */
59 zeror[degree-1] = -p[1]/p[0];
60 zeroi[degree-1] = 0.0;
64 /* Calculate the final zero or pair of zeros. */
66 quad(p[0],p[1],p[2],&zeror[degree-2],&zeroi[degree-2],
67 &zeror[degree-1],&zeroi[degree-1]);
71 /* Find largest and smallest moduli of coefficients. */
77 if (x != 0.0 && x < min){ min = x;
78 //cerr << " x= " << x << " smalno " << smalno << endl;
81 /* Scale if there are large or very small coefficients.
82 * Computes a scale factor to multiply the coefficients of the
83 * polynomial. The scaling si done to avoid overflow and to
84 * avoid undetected underflow interfering with the convergence
85 * criterion. The factor is a power of the base.
88 if (sc > 1.0 && infin/sc < max) goto _110;
90 if (max < 10.0) goto _110;
94 l = (int)(log(sc)/log(base) + 0.5);
95 factor = pow(base*1.0,l);
98 p[i] = factor*p[i]; /* Scale polynomial. */
101 /* Compute lower bound on moduli of roots. */
103 pt[i] = (fabs(p[i]));
106 /* Compute upper estimate of bound. */
107 x = exp((log(-pt[n])-log(pt[0])) / (double)n);
108 /* If Newton step at the origin is better, use it. */
109 //if (pt[n-1] != 0.0) {
110 if (fabs(pt[n-1] ) > smalno*fabs(pt[n])) {
114 /* Chop the interval (0,x) until ff <= 0 */
120 if (ff <= 0.0) break;
124 /* Do Newton interation until x converges to two
127 while (fabs(dx/x) > 0.005) {
139 /* Compute the derivative as the initial k polynomial
140 * and do 5 steps with no shift.
144 k[i] = (double)(n-i)*p[i]/(double)n;
148 zerok = (fabs(k[n-1])< smalno);
149 for(jj=0;jj<5;jj++) {
151 if (!zerok) {//cerr << "cc= " << cc << endl;
152 /* Use a scaled form of recurrence if value of k at 0 is nonzero. */
154 for (i=0;i<nm1;i++) {
156 k[j] = t*k[j-1]+p[j];
159 zerok = (fabs(k[n-1]) <= fabs(bb)*eta*10.0 || (fabs(k[n-1])< smalno));
162 /* Use unscaled form of recurrence. */
163 for (i=0;i<nm1;i++) {
168 zerok = (fabs(k[n-1])< smalno);
171 /* Save k for restarts with new shifts. */
174 /* Loop to select the quadratic corresponding to each new shift. */
175 for (cnt = 0;cnt < 20;cnt++) {
176 /* Quadratic corresponds to a double shift to a
177 * non-real point and its complex conjugate. The point
178 * has modulus bnd and amplitude rotated by 94 degrees
179 * from the previous shift.
181 xxx = cosr*xx - sinr*yy;
182 yy = sinr*xx + cosr*yy;
188 fxshfr(20*(cnt+1),&nz);
190 /* The second stage jumps directly to one of the third
191 * stage iterations and returns here if successful.
192 * Deflate the polynomial, store the zero or zeros and
193 * return to the main algorithm.
207 /* If the iteration is unsuccessful another quadratic
208 * is chosen after restoring k.
214 /* Return with failure if no convergence with 20 shifts. */
224 // cerr << " rpoly roots " << endl;
225 // for (int ii=0; ii<degree;ii++) {
226 // cerr << " (" << zeror[ii] << "," << zeroi[ii] << ")";
229 // cerr << " rpoly roots point " << &zeror[0] << " " << &zeroi[0] << endl;
230 // cerr << " rpoly roots point 1 " << &zeror[1] << " " << &zeroi[1] << endl;
236 /* Computes up to L2 fixed shift k-polynomials,
237 * testing for convergence in the linear or quadratic
238 * case. Initiates one of the variable shift
239 * iterations and returns with the number of zeros
242 void roots_polynoms::fxshfr(int l2,int *nz)
244 double svu,svv,ui,vi,s;
245 double betas,betav,oss,ovv,ss,vv,ts,tv;
246 double ots,otv,tvv,tss;
247 int type, i,j,iflag,vpass,spass,vtry,stry;
254 /* Evaluate polynomial by synthetic division. */
255 quadsd(n,&u,&v,p,qp,&a,&b);
258 /* Calculate next k polynomial and estimate v. */
261 newest(type,&ui,&vi);
265 if (k[n-1] != 0.0) ss = -p[n]/k[n-1];
268 if (j == 0 || type == 3) goto _70;
269 /* Compute relative measures of convergence of s and v sequences. */
270 if (vv != 0.0) tv = fabs((vv-ovv)/vv);
271 if (ss != 0.0) ts = fabs((ss-oss)/ss);
272 /* If decreasing, multiply two most recent convergence measures. */
274 if (tv < otv) tvv = tv*otv;
276 if (ts < ots) tss = ts*ots;
277 /* Compare with convergence criteria. */
278 vpass = (tvv < betav);
279 spass = (tss < betas);
280 if (!(spass || vpass)) goto _70;
281 /* At least one sequence has passed the convergence test.
282 * Store variables before iterating.
290 /* Choose iteration according to the fastest converging
295 if (spass && (!vpass) || tss < tvv) goto _40;
299 /* Quadratic iteration has failed. Flag that it has
300 * been tried and decrease the convergence criterion.
304 /* Try linear iteration if it has not been tried and
305 * the S sequence is converging.
307 if (stry || !spass) goto _50;
312 realit(&s,nz,&iflag);
314 /* Linear iteration has failed. Flag that it has been
315 * tried and decrease the convergence criterion.
319 if (iflag == 0) goto _50;
320 /* If linear iteration signals an almost double real
321 * zero attempt quadratic iteration.
326 /* Restore variables. */
333 /* Try quadratic iteration if it has not been tried
334 * and the V sequence is convergin.
336 if (vpass && !vtry) goto _20;
337 /* Recompute QP and scalar values to continue the
340 quadsd(n,&u,&v,p,qp,&a,&b);
349 /* Variable-shift k-polynomial iteration for a
350 * quadratic factor converges only if the zeros are
351 * equimodular or nearly so.
352 * uu, vv - coefficients of starting quadratic.
353 * nz - number of zeros found.
355 void roots_polynoms::quadit(double *uu,double *vv,int *nz)
358 double mp,omp,ee,relstp,t,zm;
368 quad(1.0,u,v,&szr,&szi,&lzr,&lzi);
369 /* Return if roots of the quadratic are real and not
370 * close to multiple or nearly equal and of opposite
373 if (fabs(fabs(szr)-fabs(lzr)) > 0.01 * fabs(lzr)) return;
374 /* Evaluate polynomial by quadratic synthetic division. */
375 quadsd(n,&u,&v,p,qp,&a,&b);
376 mp = fabs(a-szr*b) + fabs(szi*b);
377 /* Compute a rigorous bound on the rounding error in
381 ee = 2.0*fabs(qp[0]);
384 ee = ee*zm + fabs(qp[i]);
386 ee = ee*zm + fabs(a+t);
387 ee *= (5.0 *mre + 4.0*are);
388 ee = ee - (5.0*mre+2.0*are)*(fabs(a+t)+fabs(b)*zm)+2.0*are*fabs(t);
389 /* Iteration has converged sufficiently if the
390 * polynomial value is less than 20 times this bound.
397 /* Stop iteration after 20 steps. */
400 if (relstp > 0.01 || mp < omp || tried) goto _50;
401 /* A cluster appears to be stalling the convergence.
402 * Five fixed shift steps are taken with a u,v close
405 if (relstp < eta) relstp = eta;
406 relstp = sqrt(relstp);
409 quadsd(n,&u,&v,p,qp,&a,&b);
418 /* Calculate next k polynomial and new u and v. */
422 newest(type,&ui,&vi);
423 /* If vi is zero the iteration is not converging. */
424 if (vi == 0.0) return;
425 relstp = fabs((vi-v)/vi);
430 /* Variable-shift H polynomial iteration for a real zero.
431 * sss - starting iterate
432 * nz - number of zeros found
433 * iflag - flag to indicate a pair of zeros near real axis.
435 void roots_polynoms::realit(double *sss, int *nz, int *iflag)
448 /* Evaluate p at s. */
455 /* Compute a rigorous bound on the error in evaluating p. */
457 ee = (mre/(are+mre))*fabs(qp[0]);
459 ee = ee*ms + fabs(qp[i]);
461 /* Iteration has converged sufficiently if the polynomial
462 * value is less than 20 times this bound.
464 if (mp <= 20.0*((are+mre)*ee-mre*mp)) {
471 /* Stop iteration after 10 steps. */
474 if (fabs(t) > 0.001*fabs(s-t) || mp < omp) goto _50;
475 /* A cluster of zeros near the real axis has been
476 * encountered. Return with iflag set to initiate a
477 * quadratic iteration.
482 /* Return if the polynomial value has increased significantly. */
485 /* Compute t, the next polynomial, and the new iterate. */
492 if (fabs(kv) <= fabs(k[n-1])*10.0*eta) {
493 /* Use unscaled form. */
500 /* Use the scaled form of the recurrence if the value
501 * of k at s is nonzero.
506 k[i] = t*qk[i-1] + qp[i];
514 if (fabs(kv) > fabs(k[n-1]*10.0*eta)) t = -pv/kv;
519 /* This routine calculates scalar quantities used to
520 * compute the next k polynomial and new estimates of
521 * the quadratic coefficients.
522 * type - integer variable set here indicating how the
523 * calculations are normalized to avoid overflow.
525 void roots_polynoms::calcsc(int *type)
527 /* Synthetic division of k by the quadratic 1,u,v */
528 quadsd(n-1,&u,&v,k,qk,&c,&d);
529 if (fabs(c) > fabs(k[n-1]*100.0*eta)) goto _10;
530 if (fabs(d) > fabs(k[n-2]*100.0*eta)) goto _10;
532 /* Type=3 indicates the quadratic is almost a factor of k. */
535 if (fabs(d) < fabs(c)) {
537 /* Type=1 indicates that all formulas are divided by c. */
542 a3 = a*e + (h/c+g)*b;
548 /* Type=2 indicates that all formulas are divided by d. */
553 a3 = (a+g)*e + h*(b/d);
557 /* Computes the next k polynomials using scalars
558 * computed in calcsc.
560 void roots_polynoms::nextk(int *type)
566 /* Use unscaled form of the recurrence if type is 3. */
575 if (*type == 1) temp = b;
576 if (fabs(a1) <= fabs(temp)*eta*10.0) {
577 /* If a1 is nearly zero then use a special form of the
583 k[i] = a3*qk[i-2] - a7*qp[i-1];
587 /* Use scaled form of the recurrence. */
591 k[1] = qp[1] - a7*qp[0];
593 k[i] = a3*qk[i-2] - a7*qp[i-1] + qp[i];
596 /* Compute new estimates of the quadratic coefficients
597 * using the scalars computed in calcsc.
599 void roots_polynoms::newest(int type,double *uu,double *vv)
601 double a4,a5,b1,b2,c1,c2,c3,c4,temp;
602 // double smalno = 1.2e-38;
603 // double smalno = 0.0;
605 /* Use formulas appropriate to setting of type. */
607 /* If type=3 the quadratic is zeroed. */
620 /* Evaluate new quadratic coefficients. */
622 b2 = -(k[n-2]+b1*p[n-1])/p[n];
627 temp = a5 + b1*a4 - c4;
628 if (fabs(temp) <= smalno) {
633 *uu = u - (u*(c3+c2)+v*(b1*a1+b2*a7))/temp;
634 *vv = v*(1.0+c4/temp);
638 /* Divides p by the quadratic 1,u,v placing the quotient
639 * in q and the remainder in a,b.
641 void roots_polynoms::quadsd(int my_n,double *my_u,double *my_v,
642 double *my_p,double *my_q,
643 double *my_a,double *my_b)
649 *my_a = my_p[1] - (*my_b)*(*my_u);
651 for (i=2;i<=my_n;i++) {
652 my_c = my_p[i] - (*my_a)*(*my_u) - (*my_b)*(*my_v);
658 /* Calculate the zeros of the quadratic a*z^2 + b1*z + c.
659 * The quadratic formula, modified to avoid overflow, is used
660 * to find the larger zero if the zeros are real and both
661 * are complex. The smaller real zero is found directly from
662 * the product of the zeros c/a.
664 void roots_polynoms::quad(double my_a,double my_b1,double my_c,double *my_sr,double *my_si,
665 double *my_lr,double *my_li)
667 double my_b,my_d,my_e;
668 // double smalno = 1.2e-38;
670 if (fabs(my_a) <= smalno) { /* less than two roots */
671 if (fabs(my_b1) >= smalno)
672 *my_sr = -my_c/my_b1;
680 if (fabs(my_c) <= smalno) { /* one real root, one zero root */
682 *my_lr = -my_b1/my_a;
687 /* Compute discriminant avoiding overflow. */
689 if (fabs(my_b) < fabs(my_c)) {
694 my_e = my_b*(my_b/fabs(my_c)) - my_e;
695 my_d = sqrt(fabs(my_e))*sqrt(fabs(my_c));
698 my_e = 1.0 - (my_a/my_b)*(my_c/my_b);
699 my_d = sqrt(fabs(my_e))*fabs(my_b);
701 if (my_e < 0.0) { /* complex conjugate zeros */
704 *my_si = fabs(my_d/my_a);
708 if (my_b >= 0.0) /* real zeros. */
710 *my_lr = (-my_b+my_d)/my_a;
713 *my_sr = (my_c/ *my_lr)/my_a;
719 //qques outils d'algebre lineaire
722 * \brief Calcule la somme de 2vecteurs ( U=U+V)
723 * @param *U,*V les 2 vecteurs
724 * @param N taille des 2 vecteurs
725 * @return la somme de U et V dans U*/
728 double *U, //vecteur auquel on ajoute
729 int N, //taille du vecteur
730 const double *V //ajout
733 for(int i=0;i<N;i++) U[i] += V[i];
737 * \brief Calcule le tenseur de 2 vecteurs
738 * @param *a le 1er vecteur (*double)
739 * @param N la taille du premier vecteur (int)
740 * @param *b le 2ieme vecteur (*double)
741 * @param M la taille du 2ieme vecteur (int)
742 * @param *ab le resultat
745 void Polynoms::tensor
746 ( const double *a, //vecteur gauche
747 int N, //taille du vecteur gauche
748 const double *b, //vecteur droit
749 int M, //taille du vecteur droit
750 double *ab //conteneur de sortie
755 ab[i*M+j] = a[i]*b[j];
758 /** \fn matrixProduct
759 * \brief calcule le produit de 2 matrices .
760 * @param *Matrix1 la 1ere matrice
761 * @param R1,C1 la taille de la matrice1 Nbr de ligne et le nbr de colonne
762 * @param Matrix2 la 2ieme matrice
763 * @param R2,C2 la taille de la matrice2 Nbr de ligne et le nbr de colonne
764 * @param out le resultat de Matrix1*Matrix2
766 void Polynoms::matrixProduct
768 const double *Matrix1,
771 const double *Matrix2,
777 for(int i=0; i<R1; i++)
779 for(int j=0; j<C2; j++)
782 for(int k=0; k<C1; k++)
784 out[i*C2+j] += Matrix1[i*C1+k]*Matrix2[k*C2+j];
789 /** \fn matrixProdVec
790 * \brief Calcule le produit Matrice vecteur
791 * @param *Matrix correspond à la matrice du produit
792 * @param R1,C1 la taille de la matrice( Nbr de ligne et le nbr de colonne)
793 * @param Vector correspond au vecteur du produit
794 * @param out le resultat de Matrix*Vector
796 void Polynoms::matrixProdVec
797 ( const double *Matrix,
800 const double *Vector,
804 for(int i=0; i<R1; i++)
807 for(int j=0; j<C1; j++)
809 out[i] += Matrix[i*C1+j]*Vector[j];
814 /** \fn shift_diagonal
815 * \brief Calcule la trace d'une matrice carrée
816 * @param *Matrix correspond à la matrice
817 * @param N taille de la matrice
818 * @param shift résultat
819 * @return renvoie la trace de la matrice Matrix dans shift */
820 void Polynoms::shift_diagonal( double *Matrix, const int N, double shift)
822 for (int i=0; i<N; i++)
823 Matrix[i*N + i] += shift;
825 //qques outils d'algebre des polynomes
827 /** \fn remplir_trinome
828 * \brief remplie un trinome
830 void Polynoms::remplir_trinome(double coeff, double u, double alpha, vector< double >& trinome)
834 trinome[1] = -2*coeff;
836 trinome[0] = coeff - alpha;
841 * \brief Additionne 2 vecteurs de tailles differentes
842 * @param P,Q les 2 vecteurs à additionner
843 * @param n,m les 2 tailles respectives des vecteurs P et Q
844 * @return un vecteur qui correspond a P+Q*/
845 vector< double > Polynoms::additionne(const vector< double >& P, const vector< double >& Q, int n, int m)
848 vector< double > P_plus_Q = P;
849 for(int j = 0; j<m+1; j++){
855 vector< double > P_plus_Q = Q;
856 for(int j = 0; j<n+1; j++){
865 * \brief Calcule le produit scalaire de 2 vecteurs de tailles differentes
866 * @param P,Q les 2 vecteurs
867 * @param n,m les 2 tailles respectives des 2 vecteurs
868 * @return un vecteur correspond à (P,Q) */
869 vector< double > Polynoms::multiplie(const vector< double >& P, const vector< double >& Q, int n, int m)
871 vector< double > P_fois_Q (n+m+1,0.);
872 for(int i = 0; i<n+1; i++){
873 for(int j = 0; j<m+1; j++){
874 P_fois_Q[i+j] += P[i]*Q[j];
881 /** \fn polynome_caracteristique
882 * \brief Calcule le polynome caracteristique
884 vector< double > Polynoms::polynome_caracteristique(double alpha_v, double alpha_l, double Uv, double Ul, double rhov, double rhol, double cv_2, double cl_2, double dPiv, double dPil)//c= inverse vitesse du son!
886 vector< double > trinome_u(3);
887 vector< double > trinome_c(3);
888 vector< double > pol_char;
890 remplir_trinome(alpha_v*cv_2,Uv,alpha_v,trinome_c);
891 remplir_trinome(rhol,Ul,dPil,trinome_u);
893 pol_char = multiplie(trinome_u, trinome_c, 2, 2);
895 remplir_trinome(alpha_l*cl_2,Ul,alpha_l,trinome_c);
896 remplir_trinome(rhov,Uv,dPiv,trinome_u);
898 pol_char = additionne(pol_char,multiplie(trinome_u, trinome_c, 2, 2),4,4);
903 /** \fn polynome_caracteristique
920 vector< double > Polynoms::polynome_caracteristique(double alpha1, double alpha2, double u1, double u2, double rho1, double rho2, double invc1sq, double invc2sq, double dpi1, double dpi2, double g2press, double g2alpha, double g2, double epsilon)
922 vector< double > trinome1(3);
923 vector< double > trinome2(3);
924 vector< double > pol_char;
927 /* (x-u1)^2(x-u2)^2-K1(x-u2)^2-K2(x-u1)^2+K3 */
928 K1=alpha1*rho2*g2press + dpi1*alpha2*invc2sq*g2alpha;
929 K2=alpha2*rho1*g2press + dpi2*alpha1*invc1sq*g2alpha;
930 K3=(alpha1*dpi2+alpha2*dpi1)*g2alpha*g2press/g2;
931 //cout<<"K1= " <<K1<<", K2= " <<K2<<", K3= " <<K3<<endl;
933 if(fabs(K1)>epsilon && fabs(K2)>epsilon )
935 remplir_trinome(1/K1,u1,1,trinome1);
936 //cout<<"coeff constant trinome1= " << trinome1[0]<<endl;
937 remplir_trinome(1/K2,u2,1,trinome2);
938 //cout<<"coeff constant trinome2= " << trinome2[0]<<endl;
940 pol_char = multiplie(trinome1, trinome2, 2, 2);
941 //cout<<"coeff constant produit= " << pol_char[0]<<endl;
943 pol_char[0]+=K3/K2/K1-1;
944 //cout<<"coeff constant apres soustraction= " << pol_char[0]<<endl;
948 remplir_trinome(1,u1,K1,trinome1);
949 remplir_trinome(1,u2,K2,trinome2);
951 pol_char = multiplie(trinome1, trinome2, 2, 2);
953 pol_char[0]+=K3-K2*K1;
956 /* for(int ct =0; ct<pol_char.size()-1; ct++) */
957 /* if(fabs(pol_char[ct])< epsilon) */
958 /* pol_char[ct]=0.; */
963 //Pour le tri des valeurs propres
966 * \brief calcule le module d'un nombre complexe
967 * @param z est un nombre complexe
968 * @return calcule le module de z*/
969 double Polynoms::module(complex< double > z)
974 /** \fn modulec calcule le module² de z */
975 double Polynoms::modulec(complex< double > z)
980 /** \fn abs_generalise
981 * \brief calcule la valeur absolue d'un nombre complexe
982 * \Details calcule la valeur absolue d'un nombre complexe en prenant en compte
983 * que la partie réelle c-a-d si z= a+ib abs_generalize() renvoie |a|+ib
985 * @return si z = a+ib elle renvoie |a|+ib */
986 complex< double > Polynoms::abs_generalise(complex< double > z)
993 void Polynoms::ordre_croissant_abs(vector< complex< double > > &L, int n)
995 vector< complex< double > > copieL = L;
1000 for(int j=0; j<n; j++){
1002 Lmaxc = copieL[0].real();
1003 for (int i=1; i<n; i++){
1004 Lmax_iterc = copieL[i].real();
1005 if( Lmax_iterc > Lmaxc ){
1010 L[n-1-j] = copieL[i_max];
1011 copieL[i_max] = -INFINITY;
1015 int Polynoms::new_tri_selectif(vector< complex< double > > &L, int n, double epsilon)
1019 cout<<"avant ordre croissant"<<endl;
1020 for(int i=0;i<n;i++)
1021 cout<<L[i]<<", "<<endl;
1023 ordre_croissant_abs(L,n);
1025 cout<<"après ordre croissant"<<endl;
1026 for(int i=0;i<n;i++)
1027 cout<<L[i]<<", "<<endl;
1029 vector< complex< double > >result(1,L[0]);
1030 for(int i=1;i<n;i++)
1031 if(fabs(L[i].real()-result[size-1].real())>epsilon || fabs(L[i].imag())>epsilon)
1033 result.push_back(L[i]);
1036 cout<<"tri selectif step "<< i<<endl;
1037 for(int j=0;j<size;j++)
1038 cout<<result[j]<<", "<<endl;
1045 /** \fn tri_selectif
1051 template< typename T >
1052 int Polynoms::tri_selectif(T& L, int n, double epsilon)
1058 complex< double > Lmin;
1060 for(i = 0 ; i<size_vp ; i++){//On travaille sur le sous vecteur des indices de i � size_vp-1
1064 for(j = i+1 ; j < size_vp ; j++)
1065 if( Lmin.real() > L[j].real() )
1066 {Lmin = L[j]; imin = j;}
1068 //on met la vp � zero si elle est trop petite
1069 if( fabs(Lmin.real()) < epsilon) Lmin.real()=0;
1070 if( fabs(Lmin.imag()) < epsilon) Lmin.imag()=0;
1081 if ( module(L[i-1] - Lmin) > epsilon ) {
1088 L[imin]=L[size_vp - 1];
1089 L[size_vp - 1]=Lmin;
1096 if ( (module(L[i-1] - Lmin) > epsilon) && (module(L[i-2] - Lmin) > epsilon) ) {
1103 L[imin]=L[size_vp - 1];
1104 L[size_vp - 1]=Lmin;
1115 //Calcul des coefficients du polynome d'interpolation x->y dans la base de Newton
1125 vector< complex< double > > Polynoms::dif_div(int n, const vector< complex< double > >& x, const vector< T >& y, double epsilon)//n=nb valeurs à interpoler
1127 complex< double > tab_dif_div[n*n];//La matrice de taille n*n
1128 vector< complex< double > > dif_div (n);
1130 complex< double > delta_x;
1132 for( i=0 ; i<n ; i++) {
1133 tab_dif_div[i*n]=y[i];
1134 // cerr << tab_dif_div[i*n+0] << endl;
1136 for(j=1; j<n ; j++){
1137 for(i=0;i < n-j;i++) {
1138 delta_x = x[i+j]-x[i];
1139 if(module(delta_x) < epsilon) {
1140 cout << " attention, dif_div, delta_x <epsilon, " << " delta_x= " << delta_x <<" epsilon= "<<epsilon<<endl;
1141 cout<<" vp= " <<endl;
1142 for(int k=0; k<n; k++)
1143 cout << x[k]<<", " << endl;
1145 tab_dif_div[i*n+j]=(tab_dif_div[(i+1)*n+j-1]-tab_dif_div[i*n+j-1])/delta_x;
1148 for(i=0 ; i<n ; i++)
1149 dif_div[i] = tab_dif_div[i*n+n-1-i];
1152 //attention, Les vp complexes conjugu�es doivent se suivre dans la liste x
1153 void Polynoms::appliquer_dif_div(int n, const vector< complex< double > >& dif_div, const vector< complex< double > >& x, const double* A, const int sizeA, double epsilon, double *p)//p=result
1156 double Id[sizeA*sizeA], aux[sizeA*sizeA], matProd[sizeA*sizeA];
1158 for(int k=0; k<sizeA*sizeA; k++)
1160 for(int k=0; k<sizeA; k++)
1162 /* for(int k=0; k<sizeA*sizeA; k++) */
1163 /* aux[k] = A[k] ; */
1164 //cerr << x << endl;
1165 if( fabs(x[0].imag()) > epsilon){
1166 for(int k=0; k<sizeA*sizeA; k++)
1167 p[k] = A[k] * dif_div[0].real() ;
1168 shift_diagonal(p, sizeA,(dif_div[1] - dif_div[0]*x[1]).real());
1171 for(int k=0; k<sizeA*sizeA; k++)
1172 p[k] = Id[k] * dif_div[0].real() ;
1174 for(i=debut ; i<n ; i++){
1175 for(int k=0; k<sizeA*sizeA; k++)
1177 //cerr << " on traite la racine reele " << x[i] << endl;
1178 if ( fabs(x[i].imag()) < epsilon ) {
1179 shift_diagonal(aux, sizeA, (- x[i].real()));
1180 matrixProduct( p, sizeA, sizeA, aux, sizeA, sizeA, matProd);
1181 for(int k=0; k<sizeA*sizeA; k++)
1183 shift_diagonal(p, sizeA, dif_div[i].real());
1185 else{ //couple de conjugees
1186 if(fabs(x[i].imag() + x[i+1].imag()) < epsilon){
1187 matrixProduct( aux, sizeA, sizeA, aux, sizeA, sizeA, matProd);
1188 for(int k=0; k<sizeA*sizeA; k++)
1189 aux[k] = matProd[k];
1190 for(int k=0; k<sizeA*sizeA; k++)
1191 aux[k]+=(-2*x[i].real()) * A[k];
1192 shift_diagonal(aux, sizeA, modulec(x[i]));
1194 matrixProduct( p, sizeA, sizeA, aux, sizeA, sizeA, matProd);
1195 for(int k=0; k<sizeA*sizeA; k++)
1197 for(int k=0; k<sizeA*sizeA; k++)
1198 p[k]+= dif_div[i].real() * A[k];
1199 shift_diagonal(p, sizeA, (dif_div[i+1] - dif_div[i]*x[i+1]).real());
1203 cout << " appliquer_dif_div : les racines complexes conjuguees ne se suivent pas " << endl;
1204 for(int k=0; k<n; k++)
1205 cout << x[k]<<", " << endl;
1206 throw(" appliquer_dif_div : les racines complexes conjuguees ne se suivent pas ");
1212 void Polynoms::abs_par_interp_directe(int n, vector< complex< double > > vp, double * A, int sizeA, double epsilon, double *result,vector< complex< double > > y)
1214 vector< complex< double > > differences_divisees = dif_div(n, vp, y, epsilon);
1216 cout<<"valeurs propres"<<endl;
1217 for( int i=0 ; i<n ; i++)
1218 cout<<vp[i] <<", "<<endl;
1219 cout<<"valeurs à atteindre"<<endl;
1220 for( int i=0 ; i<n ; i++)
1221 cout<<y[i] <<", "<<endl;
1222 cout<<"differences_divisees= "<<endl;
1223 for(int i=0 ; i<n ; i++)
1224 cout<<differences_divisees[i]<<", ";
1227 appliquer_dif_div(n, differences_divisees, vp, A, sizeA, epsilon, result);
1230 bool Polynoms::belongTo(complex< double > a , vector< complex <double > > v, double epsilon)
1232 bool result = false;
1233 int size = v.size();
1235 double epsilon2 = epsilon*epsilon;
1237 while(i<size && !result)
1239 result = modulec(a-v[i]) < epsilon2;
1244 double Polynoms::avr(double a, double b)