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