1 /*
2  * (C) Vladislav Malyshkin 2010
3  * This file is under GPL version 3.
4  *
5  */
6 
7 /** Polynomial root.
8  *  @version $Id: PolynomialRoot.java,v 1.105 2012/08/18 00:00:05 mal Exp $
9  *  @author Vladislav Malyshkin mal@gromco.com
10  */
11 
12 /**
13  * @test
14  * @bug 8005956
15  * @summary C2: assert(!def_outside->member(r)) failed: Use of external LRG overlaps the same LRG defined in this block
16  * @library /test/lib
17  * @modules java.base/jdk.internal.misc
18  *          java.management
19  *
20  * @run main/timeout=300 compiler.c2.PolynomialRoot
21  */
22 
23 package compiler.c2;
24 
25 import jdk.test.lib.Utils;
26 
27 import java.util.Arrays;
28 import java.util.Random;
29 
30 public class PolynomialRoot  {
31 
32 
findPolynomialRoots(final int n, final double [] p, final double [] re_root, final double [] im_root)33 public static int findPolynomialRoots(final int n,
34               final double [] p,
35               final double [] re_root,
36               final double [] im_root)
37 {
38     if(n==4)
39     {
40   return root4(p,re_root,im_root);
41     }
42     else if(n==3)
43     {
44   return root3(p,re_root,im_root);
45     }
46     else if(n==2)
47     {
48   return root2(p,re_root,im_root);
49     }
50     else if(n==1)
51     {
52   return root1(p,re_root,im_root);
53     }
54     else
55     {
56   throw new RuntimeException("n="+n+" is not supported yet");
57     }
58 }
59 
60 
61 
62 static final double SQRT3=Math.sqrt(3.0),SQRT2=Math.sqrt(2.0);
63 
64 
65 private static final boolean PRINT_DEBUG=false;
66 
root4(final double [] p,final double [] re_root,final double [] im_root)67 public static int root4(final double [] p,final double [] re_root,final double [] im_root)
68 {
69   if (PRINT_DEBUG) { System.err.println("=====================root4:p=" + Arrays.toString(p)); }
70   final double vs=p[4];
71   if(PRINT_DEBUG) System.err.println("p[4]="+p[4]);
72   if(!(Math.abs(vs)>EPS))
73   {
74       re_root[0]=re_root[1]=re_root[2]=re_root[3]=
75     im_root[0]=im_root[1]=im_root[2]=im_root[3]=Double.NaN;
76       return -1;
77   }
78 
79 /* zsolve_quartic.c - finds the complex roots of
80  *  x^4 + a x^3 + b x^2 + c x + d = 0
81  */
82   final double a=p[3]/vs,b=p[2]/vs,c=p[1]/vs,d=p[0]/vs;
83   if(PRINT_DEBUG) System.err.println("input a="+a+" b="+b+" c="+c+" d="+d);
84 
85 
86   final double r4 = 1.0 / 4.0;
87   final double q2 = 1.0 / 2.0, q4 = 1.0 / 4.0, q8 = 1.0 / 8.0;
88   final double q1 = 3.0 / 8.0, q3 = 3.0 / 16.0;
89   final int mt;
90 
91   /* Deal easily with the cases where the quartic is degenerate. The
92    * ordering of solutions is done explicitly. */
93   if (0 == b && 0 == c)
94   {
95       if (0 == d)
96       {
97     re_root[0]=-a;
98     im_root[0]=im_root[1]=im_root[2]=im_root[3]=0;
99     re_root[1]=re_root[2]=re_root[3]=0;
100     return 4;
101       }
102       else if (0 == a)
103       {
104     if (d > 0)
105     {
106         final double sq4 = Math.sqrt(Math.sqrt(d));
107         re_root[0]=sq4*SQRT2/2;
108         im_root[0]=re_root[0];
109         re_root[1]=-re_root[0];
110         im_root[1]=re_root[0];
111         re_root[2]=-re_root[0];
112         im_root[2]=-re_root[0];
113         re_root[3]=re_root[0];
114         im_root[3]=-re_root[0];
115         if(PRINT_DEBUG) System.err.println("Path a=0 d>0");
116     }
117     else
118     {
119         final double sq4 = Math.sqrt(Math.sqrt(-d));
120         re_root[0]=sq4;
121         im_root[0]=0;
122         re_root[1]=0;
123         im_root[1]=sq4;
124         re_root[2]=0;
125         im_root[2]=-sq4;
126         re_root[3]=-sq4;
127         im_root[3]=0;
128         if(PRINT_DEBUG) System.err.println("Path a=0 d<0");
129     }
130     return 4;
131       }
132   }
133 
134   if (0.0 == c && 0.0 == d)
135   {
136       root2(new double []{p[2],p[3],p[4]},re_root,im_root);
137       re_root[2]=im_root[2]=re_root[3]=im_root[3]=0;
138       return 4;
139   }
140 
141   if(PRINT_DEBUG) System.err.println("G Path c="+c+" d="+d);
142   final double [] u=new double[3];
143 
144   if(PRINT_DEBUG) System.err.println("Generic Path");
145   /* For non-degenerate solutions, proceed by constructing and
146    * solving the resolvent cubic */
147   final double aa = a * a;
148   final double pp = b - q1 * aa;
149   final double qq = c - q2 * a * (b - q4 * aa);
150   final double rr = d - q4 * a * (c - q4 * a * (b - q3 * aa));
151   final double rc = q2 * pp , rc3 = rc / 3;
152   final double sc = q4 * (q4 * pp * pp - rr);
153   final double tc = -(q8 * qq * q8 * qq);
154   if(PRINT_DEBUG) System.err.println("aa="+aa+" pp="+pp+" qq="+qq+" rr="+rr+" rc="+rc+" sc="+sc+" tc="+tc);
155   final boolean flag_realroots;
156 
157   /* This code solves the resolvent cubic in a convenient fashion
158    * for this implementation of the quartic. If there are three real
159    * roots, then they are placed directly into u[].  If two are
160    * complex, then the real root is put into u[0] and the real
161    * and imaginary part of the complex roots are placed into
162    * u[1] and u[2], respectively. */
163   {
164       final double qcub = (rc * rc - 3 * sc);
165       final double rcub = (rc*(2 * rc * rc - 9 * sc) + 27 * tc);
166 
167       final double Q = qcub / 9;
168       final double R = rcub / 54;
169 
170       final double Q3 = Q * Q * Q;
171       final double R2 = R * R;
172 
173       final double CR2 = 729 * rcub * rcub;
174       final double CQ3 = 2916 * qcub * qcub * qcub;
175 
176       if(PRINT_DEBUG) System.err.println("CR2="+CR2+" CQ3="+CQ3+" R="+R+" Q="+Q);
177 
178       if (0 == R && 0 == Q)
179       {
180     flag_realroots=true;
181     u[0] = -rc3;
182     u[1] = -rc3;
183     u[2] = -rc3;
184       }
185       else if (CR2 == CQ3)
186       {
187     flag_realroots=true;
188     final double sqrtQ = Math.sqrt (Q);
189     if (R > 0)
190     {
191         u[0] = -2 * sqrtQ - rc3;
192         u[1] = sqrtQ - rc3;
193         u[2] = sqrtQ - rc3;
194     }
195     else
196     {
197         u[0] = -sqrtQ - rc3;
198         u[1] = -sqrtQ - rc3;
199         u[2] = 2 * sqrtQ - rc3;
200     }
201       }
202       else if (R2 < Q3)
203       {
204     flag_realroots=true;
205     final double ratio = (R >= 0?1:-1) * Math.sqrt (R2 / Q3);
206     final double theta = Math.acos (ratio);
207     final double norm = -2 * Math.sqrt (Q);
208 
209     u[0] = norm * Math.cos (theta / 3) - rc3;
210     u[1] = norm * Math.cos ((theta + 2.0 * Math.PI) / 3) - rc3;
211     u[2] = norm * Math.cos ((theta - 2.0 * Math.PI) / 3) - rc3;
212       }
213       else
214       {
215     flag_realroots=false;
216     final double A = -(R >= 0?1:-1)*Math.pow(Math.abs(R)+Math.sqrt(R2-Q3),1.0/3.0);
217     final double B = Q / A;
218 
219     u[0] = A + B - rc3;
220     u[1] = -0.5 * (A + B) - rc3;
221     u[2] = -(SQRT3*0.5) * Math.abs (A - B);
222       }
223       if(PRINT_DEBUG) System.err.println("u[0]="+u[0]+" u[1]="+u[1]+" u[2]="+u[2]+" qq="+qq+" disc="+((CR2 - CQ3) / 2125764.0));
224   }
225   /* End of solution to resolvent cubic */
226 
227   /* Combine the square roots of the roots of the cubic
228    * resolvent appropriately. Also, calculate 'mt' which
229    * designates the nature of the roots:
230    * mt=1 : 4 real roots
231    * mt=2 : 0 real roots
232    * mt=3 : 2 real roots
233    */
234 
235 
236   final double w1_re,w1_im,w2_re,w2_im,w3_re,w3_im,mod_w1w2,mod_w1w2_squared;
237   if (flag_realroots)
238   {
239       mod_w1w2=-1;
240       mt = 2;
241       int jmin=0;
242       double vmin=Math.abs(u[jmin]);
243       for(int j=1;j<3;j++)
244       {
245     final double vx=Math.abs(u[j]);
246     if(vx<vmin)
247     {
248         vmin=vx;
249         jmin=j;
250     }
251       }
252       final double u1=u[(jmin+1)%3],u2=u[(jmin+2)%3];
253       mod_w1w2_squared=Math.abs(u1*u2);
254       if(u1>=0)
255       {
256     w1_re=Math.sqrt(u1);
257     w1_im=0;
258       }
259       else
260       {
261     w1_re=0;
262     w1_im=Math.sqrt(-u1);
263       }
264       if(u2>=0)
265       {
266     w2_re=Math.sqrt(u2);
267     w2_im=0;
268       }
269       else
270       {
271     w2_re=0;
272     w2_im=Math.sqrt(-u2);
273       }
274       if(PRINT_DEBUG) System.err.println("u1="+u1+" u2="+u2+" jmin="+jmin);
275   }
276   else
277   {
278       mt = 3;
279       final double w_mod2_sq=u[1]*u[1]+u[2]*u[2],w_mod2=Math.sqrt(w_mod2_sq),w_mod=Math.sqrt(w_mod2);
280       if(w_mod2_sq<=0)
281       {
282     w1_re=w1_im=0;
283       }
284       else
285       {
286     // calculate square root of a complex number (u[1],u[2])
287     // the result is in the (w1_re,w1_im)
288     final double absu1=Math.abs(u[1]),absu2=Math.abs(u[2]),w;
289     if(absu1>=absu2)
290     {
291         final double t=absu2/absu1;
292         w=Math.sqrt(absu1*0.5 * (1.0 + Math.sqrt(1.0 + t * t)));
293         if(PRINT_DEBUG) System.err.println(" Path1 ");
294     }
295     else
296     {
297         final double t=absu1/absu2;
298         w=Math.sqrt(absu2*0.5 * (t + Math.sqrt(1.0 + t * t)));
299         if(PRINT_DEBUG) System.err.println(" Path1a ");
300     }
301     if(u[1]>=0)
302     {
303         w1_re=w;
304         w1_im=u[2]/(2*w);
305         if(PRINT_DEBUG) System.err.println(" Path2 ");
306     }
307     else
308     {
309         final double vi = (u[2] >= 0) ? w : -w;
310         w1_re=u[2]/(2*vi);
311         w1_im=vi;
312         if(PRINT_DEBUG) System.err.println(" Path2a ");
313     }
314       }
315       final double absu0=Math.abs(u[0]);
316       if(w_mod2>=absu0)
317       {
318     mod_w1w2=w_mod2;
319     mod_w1w2_squared=w_mod2_sq;
320     w2_re=w1_re;
321     w2_im=-w1_im;
322       }
323       else
324       {
325     mod_w1w2=-1;
326     mod_w1w2_squared=w_mod2*absu0;
327     if(u[0]>=0)
328     {
329         w2_re=Math.sqrt(absu0);
330         w2_im=0;
331     }
332     else
333     {
334         w2_re=0;
335         w2_im=Math.sqrt(absu0);
336     }
337       }
338       if(PRINT_DEBUG) System.err.println("u[0]="+u[0]+"u[1]="+u[1]+" u[2]="+u[2]+" absu0="+absu0+" w_mod="+w_mod+" w_mod2="+w_mod2);
339   }
340 
341   /* Solve the quadratic in order to obtain the roots
342    * to the quartic */
343   if(mod_w1w2>0)
344   {
345       // a shorcut to reduce rounding error
346       w3_re=qq/(-8)/mod_w1w2;
347       w3_im=0;
348   }
349   else if(mod_w1w2_squared>0)
350   {
351       // regular path
352       final double mqq8n=qq/(-8)/mod_w1w2_squared;
353       w3_re=mqq8n*(w1_re*w2_re-w1_im*w2_im);
354       w3_im=-mqq8n*(w1_re*w2_im+w2_re*w1_im);
355   }
356   else
357   {
358       // typically occur when qq==0
359       w3_re=w3_im=0;
360   }
361 
362   final double h = r4 * a;
363   if(PRINT_DEBUG) System.err.println("w1_re="+w1_re+" w1_im="+w1_im+" w2_re="+w2_re+" w2_im="+w2_im+" w3_re="+w3_re+" w3_im="+w3_im+" h="+h);
364 
365   re_root[0]=w1_re+w2_re+w3_re-h;
366   im_root[0]=w1_im+w2_im+w3_im;
367   re_root[1]=-(w1_re+w2_re)+w3_re-h;
368   im_root[1]=-(w1_im+w2_im)+w3_im;
369   re_root[2]=w2_re-w1_re-w3_re-h;
370   im_root[2]=w2_im-w1_im-w3_im;
371   re_root[3]=w1_re-w2_re-w3_re-h;
372   im_root[3]=w1_im-w2_im-w3_im;
373 
374   return 4;
375 }
376 
377 
378 
setRandomP(final double [] p, final int n, Random r)379     static void setRandomP(final double [] p, final int n, Random r)
380     {
381   if(r.nextDouble()<0.1)
382   {
383       // integer coefficiens
384       for(int j=0;j<p.length;j++)
385       {
386     if(j<=n)
387     {
388         p[j]=(r.nextInt(2)<=0?-1:1)*r.nextInt(10);
389     }
390     else
391     {
392         p[j]=0;
393     }
394       }
395   }
396   else
397   {
398       // real coefficiens
399       for(int j=0;j<p.length;j++)
400       {
401     if(j<=n)
402     {
403         p[j]=-1+2*r.nextDouble();
404     }
405     else
406     {
407         p[j]=0;
408     }
409       }
410   }
411   if(Math.abs(p[n])<1e-2)
412   {
413       p[n]=(r.nextInt(2)<=0?-1:1)*(0.1+r.nextDouble());
414   }
415     }
416 
417 
checkValues(final double [] p, final int n, final double rex, final double imx, final double eps, final String txt)418     static void checkValues(final double [] p,
419           final int n,
420           final double rex,
421           final double imx,
422           final double eps,
423           final String txt)
424     {
425   double res=0,ims=0,sabs=0;
426   final double xabs=Math.abs(rex)+Math.abs(imx);
427   for(int k=n;k>=0;k--)
428   {
429       final double res1=(res*rex-ims*imx)+p[k];
430       final double ims1=(ims*rex+res*imx);
431       res=res1;
432       ims=ims1;
433       sabs+=xabs*sabs+p[k];
434   }
435   sabs=Math.abs(sabs);
436   if(false && sabs>1/eps?
437      (!(Math.abs(res/sabs)<=eps)||!(Math.abs(ims/sabs)<=eps))
438      :
439      (!(Math.abs(res)<=eps)||!(Math.abs(ims)<=eps)))
440   {
441       throw new RuntimeException(
442     getPolinomTXT(p)+"\n"+
443     "\t x.r="+rex+" x.i="+imx+"\n"+
444     "res/sabs="+(res/sabs)+" ims/sabs="+(ims/sabs)+
445     " sabs="+sabs+
446     "\nres="+res+" ims="+ims+" n="+n+" eps="+eps+" "+
447     " sabs>1/eps="+(sabs>1/eps)+
448     " f1="+(!(Math.abs(res/sabs)<=eps)||!(Math.abs(ims/sabs)<=eps))+
449     " f2="+(!(Math.abs(res)<=eps)||!(Math.abs(ims)<=eps))+
450     " "+txt);
451   }
452     }
453 
getPolinomTXT(final double [] p)454     static String getPolinomTXT(final double [] p)
455     {
456   final StringBuilder buf=new StringBuilder();
457   buf.append("order="+(p.length-1)+"\t");
458   for(int k=0;k<p.length;k++)
459   {
460       buf.append("p["+k+"]="+p[k]+";");
461   }
462   return buf.toString();
463     }
464 
getRootsTXT(int nr,final double [] re,final double [] im)465     static String getRootsTXT(int nr,final double [] re,final double [] im)
466     {
467   final StringBuilder buf=new StringBuilder();
468   for(int k=0;k<nr;k++)
469   {
470       buf.append("x."+k+"("+re[k]+","+im[k]+")\n");
471   }
472   return buf.toString();
473     }
474 
testRoots(final int n, final int n_tests, final Random rn, final double eps)475     static void testRoots(final int n,
476         final int n_tests,
477         final Random rn,
478         final double eps)
479     {
480   final double [] p=new double [n+1];
481   final double [] rex=new double [n],imx=new double [n];
482   for(int i=0;i<n_tests;i++)
483   {
484     for(int dg=n;dg-->-1;)
485     {
486       for(int dr=3;dr-->0;)
487       {
488         setRandomP(p,n,rn);
489         for(int j=0;j<=dg;j++)
490         {
491       p[j]=0;
492         }
493         if(dr==0)
494         {
495       p[0]=-1+2.0*rn.nextDouble();
496         }
497         else if(dr==1)
498         {
499       p[0]=p[1]=0;
500         }
501 
502         findPolynomialRoots(n,p,rex,imx);
503 
504         for(int j=0;j<n;j++)
505         {
506       //System.err.println("j="+j);
507       checkValues(p,n,rex[j],imx[j],eps," t="+i);
508         }
509       }
510     }
511   }
512   System.err.println("testRoots(): n_tests="+n_tests+" OK, dim="+n);
513     }
514 
515 
516 
517 
518     static final double EPS=0;
519 
root1(final double [] p,final double [] re_root,final double [] im_root)520     public static int root1(final double [] p,final double [] re_root,final double [] im_root)
521     {
522   if(!(Math.abs(p[1])>EPS))
523   {
524       re_root[0]=im_root[0]=Double.NaN;
525       return -1;
526   }
527   re_root[0]=-p[0]/p[1];
528   im_root[0]=0;
529   return 1;
530     }
531 
root2(final double [] p,final double [] re_root,final double [] im_root)532     public static int root2(final double [] p,final double [] re_root,final double [] im_root)
533     {
534   if(!(Math.abs(p[2])>EPS))
535   {
536       re_root[0]=re_root[1]=im_root[0]=im_root[1]=Double.NaN;
537       return -1;
538   }
539   final double b2=0.5*(p[1]/p[2]),c=p[0]/p[2],d=b2*b2-c;
540   if(d>=0)
541   {
542       final double sq=Math.sqrt(d);
543       if(b2<0)
544       {
545     re_root[1]=-b2+sq;
546     re_root[0]=c/re_root[1];
547       }
548       else if(b2>0)
549       {
550     re_root[0]=-b2-sq;
551     re_root[1]=c/re_root[0];
552       }
553       else
554       {
555     re_root[0]=-b2-sq;
556     re_root[1]=-b2+sq;
557       }
558       im_root[0]=im_root[1]=0;
559   }
560   else
561   {
562       final double sq=Math.sqrt(-d);
563       re_root[0]=re_root[1]=-b2;
564       im_root[0]=sq;
565       im_root[1]=-sq;
566   }
567   return 2;
568     }
569 
root3(final double [] p,final double [] re_root,final double [] im_root)570     public static int root3(final double [] p,final double [] re_root,final double [] im_root)
571     {
572   final double vs=p[3];
573   if(!(Math.abs(vs)>EPS))
574   {
575       re_root[0]=re_root[1]=re_root[2]=
576     im_root[0]=im_root[1]=im_root[2]=Double.NaN;
577       return -1;
578   }
579   final double a=p[2]/vs,b=p[1]/vs,c=p[0]/vs;
580   /* zsolve_cubic.c - finds the complex roots of x^3 + a x^2 + b x + c = 0
581    */
582   final double q = (a * a - 3 * b);
583   final double r = (a*(2 * a * a - 9 * b) + 27 * c);
584 
585   final double Q = q / 9;
586   final double R = r / 54;
587 
588   final double Q3 = Q * Q * Q;
589   final double R2 = R * R;
590 
591   final double CR2 = 729 * r * r;
592   final double CQ3 = 2916 * q * q * q;
593   final double a3=a/3;
594 
595   if (R == 0 && Q == 0)
596   {
597       re_root[0]=re_root[1]=re_root[2]=-a3;
598       im_root[0]=im_root[1]=im_root[2]=0;
599       return 3;
600   }
601   else if (CR2 == CQ3)
602   {
603       /* this test is actually R2 == Q3, written in a form suitable
604          for exact computation with integers */
605 
606       /* Due to finite precision some double roots may be missed, and
607          will be considered to be a pair of complex roots z = x +/-
608          epsilon i close to the real axis. */
609 
610       final double sqrtQ = Math.sqrt (Q);
611 
612       if (R > 0)
613       {
614     re_root[0] = -2 * sqrtQ - a3;
615     re_root[1]=re_root[2]=sqrtQ - a3;
616     im_root[0]=im_root[1]=im_root[2]=0;
617       }
618       else
619       {
620     re_root[0]=re_root[1] = -sqrtQ - a3;
621     re_root[2]=2 * sqrtQ - a3;
622     im_root[0]=im_root[1]=im_root[2]=0;
623       }
624       return 3;
625   }
626   else if (R2 < Q3)
627   {
628       final double sgnR = (R >= 0 ? 1 : -1);
629       final double ratio = sgnR * Math.sqrt (R2 / Q3);
630       final double theta = Math.acos (ratio);
631       final double norm = -2 * Math.sqrt (Q);
632       final double r0 = norm * Math.cos (theta/3) - a3;
633       final double r1 = norm * Math.cos ((theta + 2.0 * Math.PI) / 3) - a3;
634       final double r2 = norm * Math.cos ((theta - 2.0 * Math.PI) / 3) - a3;
635 
636       re_root[0]=r0;
637       re_root[1]=r1;
638       re_root[2]=r2;
639       im_root[0]=im_root[1]=im_root[2]=0;
640       return 3;
641   }
642   else
643   {
644       final double sgnR = (R >= 0 ? 1 : -1);
645       final double A = -sgnR * Math.pow (Math.abs (R) + Math.sqrt (R2 - Q3), 1.0 / 3.0);
646       final double B = Q / A;
647 
648       re_root[0]=A + B - a3;
649       im_root[0]=0;
650       re_root[1]=-0.5 * (A + B) - a3;
651       im_root[1]=-(SQRT3*0.5) * Math.abs(A - B);
652       re_root[2]=re_root[1];
653       im_root[2]=-im_root[1];
654       return 3;
655   }
656 
657     }
658 
659 
root3a(final double [] p,final double [] re_root,final double [] im_root)660     static void root3a(final double [] p,final double [] re_root,final double [] im_root)
661     {
662   if(Math.abs(p[3])>EPS)
663   {
664       final double v=p[3],
665     a=p[2]/v,b=p[1]/v,c=p[0]/v,
666     a3=a/3,a3a=a3*a,
667     pd3=(b-a3a)/3,
668     qd2=a3*(a3a/3-0.5*b)+0.5*c,
669     Q=pd3*pd3*pd3+qd2*qd2;
670       if(Q<0)
671       {
672     // three real roots
673     final double SQ=Math.sqrt(-Q);
674     final double th=Math.atan2(SQ,-qd2);
675     im_root[0]=im_root[1]=im_root[2]=0;
676     final double f=2*Math.sqrt(-pd3);
677     re_root[0]=f*Math.cos(th/3)-a3;
678     re_root[1]=f*Math.cos((th+2*Math.PI)/3)-a3;
679     re_root[2]=f*Math.cos((th+4*Math.PI)/3)-a3;
680     //System.err.println("3r");
681       }
682       else
683       {
684     // one real & two complex roots
685     final double SQ=Math.sqrt(Q);
686     final double r1=-qd2+SQ,r2=-qd2-SQ;
687     final double v1=Math.signum(r1)*Math.pow(Math.abs(r1),1.0/3),
688         v2=Math.signum(r2)*Math.pow(Math.abs(r2),1.0/3),
689         sv=v1+v2;
690     // real root
691     re_root[0]=sv-a3;
692     im_root[0]=0;
693     // complex roots
694     re_root[1]=re_root[2]=-0.5*sv-a3;
695     im_root[1]=(v1-v2)*(SQRT3*0.5);
696     im_root[2]=-im_root[1];
697     //System.err.println("1r2c");
698       }
699   }
700   else
701   {
702       re_root[0]=re_root[1]=re_root[2]=im_root[0]=im_root[1]=im_root[2]=Double.NaN;
703   }
704     }
705 
706 
printSpecialValues()707     static void printSpecialValues()
708     {
709   for(int st=0;st<6;st++)
710   {
711       //final double [] p=new double []{8,1,3,3.6,1};
712       final double [] re_root=new double [4],im_root=new double [4];
713       final double [] p;
714       final int n;
715       if(st<=3)
716       {
717     if(st<=0)
718     {
719         p=new double []{2,-4,6,-4,1};
720         //p=new double []{-6,6,-6,8,-2};
721     }
722     else if(st==1)
723     {
724         p=new double []{0,-4,8,3,-9};
725     }
726     else if(st==2)
727     {
728         p=new double []{-1,0,2,0,-1};
729     }
730     else
731     {
732         p=new double []{-5,2,8,-2,-3};
733     }
734     root4(p,re_root,im_root);
735     n=4;
736       }
737       else
738       {
739     p=new double []{0,2,0,1};
740     if(st==4)
741     {
742         p[1]=-p[1];
743     }
744     root3(p,re_root,im_root);
745     n=3;
746       }
747       System.err.println("======== n="+n);
748       for(int i=0;i<=n;i++)
749       {
750     if(i<n)
751     {
752         System.err.println(String.valueOf(i)+"\t"+
753                p[i]+"\t"+
754                re_root[i]+"\t"+
755                im_root[i]);
756     }
757     else
758     {
759         System.err.println(String.valueOf(i)+"\t"+p[i]+"\t");
760     }
761       }
762   }
763     }
764 
765 
766 
main(final String [] args)767     public static void main(final String [] args)
768     {
769       if (System.getProperty("os.arch").equals("x86") ||
770          System.getProperty("os.arch").equals("amd64") ||
771          System.getProperty("os.arch").equals("x86_64")){
772         final long t0=System.currentTimeMillis();
773         final double eps=1e-6;
774         //checkRoots();
775         final Random r = Utils.getRandomInstance();
776         printSpecialValues();
777 
778         final int n_tests=100000;
779         //testRoots(2,n_tests,r,eps);
780         //testRoots(3,n_tests,r,eps);
781         testRoots(4,n_tests,r,eps);
782         final long t1=System.currentTimeMillis();
783         System.err.println("PolynomialRoot.main: "+n_tests+" tests OK done in "+(t1-t0)+" milliseconds. ver=$Id: PolynomialRoot.java,v 1.105 2012/08/18 00:00:05 mal Exp $");
784         System.out.println("PASSED");
785      } else {
786        System.out.println("PASS test for non-x86");
787      }
788    }
789 
790 
791 
792 }
793