001/*
002 * $Id: ComplexRootTest.java 5863 2018-07-20 11:13:34Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import junit.framework.Test;
013import junit.framework.TestCase;
014import junit.framework.TestSuite;
015
016import edu.jas.arith.BigDecimal;
017import edu.jas.arith.BigRational;
018import edu.jas.kern.ComputerThreads;
019import edu.jas.poly.Complex;
020import edu.jas.poly.ComplexRing;
021import edu.jas.poly.GenPolynomial;
022import edu.jas.poly.GenPolynomialRing;
023import edu.jas.poly.PolyUtil;
024import edu.jas.poly.TermOrder;
025import edu.jas.structure.Power;
026import edu.jas.ufd.Squarefree;
027import edu.jas.ufd.SquarefreeFactory;
028
029
030/**
031 * RootUtil tests with JUnit.
032 * @author Heinz Kredel
033 */
034
035public class ComplexRootTest extends TestCase {
036
037
038    /**
039     * main.
040     */
041    public static void main(String[] args) {
042        junit.textui.TestRunner.run(suite());
043        ComputerThreads.terminate();
044    }
045
046
047    /**
048     * Constructs a <CODE>ComplexRootTest</CODE> object.
049     * @param name String.
050     */
051    public ComplexRootTest(String name) {
052        super(name);
053    }
054
055
056    /**
057     */
058    public static Test suite() {
059        TestSuite suite = new TestSuite(ComplexRootTest.class);
060        return suite;
061    }
062
063
064    TermOrder to = new TermOrder(TermOrder.INVLEX);
065
066
067    GenPolynomialRing<Complex<BigRational>> dfac;
068
069
070    ComplexRing<BigRational> cfac;
071
072
073    BigRational eps;
074
075
076    Complex<BigRational> ceps;
077
078
079    GenPolynomial<Complex<BigRational>> a;
080
081
082    GenPolynomial<Complex<BigRational>> b;
083
084
085    GenPolynomial<Complex<BigRational>> c;
086
087
088    GenPolynomial<Complex<BigRational>> d;
089
090
091    GenPolynomial<Complex<BigRational>> e;
092
093
094    int rl = 1;
095
096
097    int kl = 3;
098
099
100    int ll = 3;
101
102
103    int el = 5;
104
105
106    float q = 0.7f;
107
108
109    @Override
110    protected void setUp() {
111        a = b = c = d = e = null;
112        cfac = new ComplexRing<BigRational>(new BigRational(1));
113        String[] vars = new String[] { "x" };
114        dfac = new GenPolynomialRing<Complex<BigRational>>(cfac, rl, to, vars);
115        eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION);
116        ceps = new Complex<BigRational>(cfac, eps);
117    }
118
119
120    @Override
121    protected void tearDown() {
122        a = b = c = d = e = null;
123        dfac = null;
124        cfac = null;
125        eps = null;
126    }
127
128
129    /**
130     * Test root bound.
131     * 
132     */
133    public void testRootBound() {
134        //a = dfac.random(kl, ll, el, q);
135        a = dfac.univariate(0, 2L).sum(dfac.getONE()); // x^2 + 1
136        //System.out.println("a = " + a);
137
138        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
139
140        Complex<BigRational> Mb = cr.rootBound(a);
141        BigRational M = Mb.getRe();
142
143        //System.out.println("M = " + M);
144        assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0);
145
146        //a = a.monic();
147        a = a.multiply(dfac.fromInteger(5));
148        //System.out.println("a = " + a);
149        M = cr.rootBound(a).getRe();
150
151        //System.out.println("M = " + M);
152        assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0);
153    }
154
155
156    /**
157     * Test Cauchy index.
158     * 
159     */
160    public void testCauchyIndex() {
161        a = dfac.random(kl, ll, el, q);
162        b = dfac.random(kl, ll, el, q);
163        //a = dfac.univariate(0,2L).sum(dfac.getONE());  // x^2 + 1
164        //System.out.println("a = " + a);
165        //System.out.println("b = " + b);
166
167        BigRational l = new BigRational(0);
168        BigRational r = new BigRational(1);
169        GenPolynomialRing<BigRational> fac = new GenPolynomialRing<BigRational>(l, dfac);
170
171        ComplexRootsSturm<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
172
173        GenPolynomial<BigRational> f = PolyUtil.<BigRational> realPartFromComplex(fac, a);
174        GenPolynomial<BigRational> g = PolyUtil.<BigRational> imaginaryPartFromComplex(fac, b);
175        //System.out.println("re(a) = " + f);
176        //System.out.println("im(b) = " + g);
177
178        long ci = cr.indexOfCauchy(l, r, g, f);
179        //System.out.println("ci = " + ci);
180
181        assertTrue("ci >= 0 ", ci >= -a.degree(0));
182    }
183
184
185    /**
186     * Test Routh.
187     * 
188     */
189    public void testRouth() {
190        ComplexRootsSturm<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
191
192        //a = dfac.random(kl, ll, el, q);
193        //b = dfac.random(kl, ll, el, q);
194        Complex<BigRational> I = cfac.getIMAG();
195        GenPolynomial<Complex<BigRational>> X = dfac.univariate(0);
196        //System.out.println("I = " + I);
197        //System.out.println("X = " + X);
198
199        //a = dfac.univariate(0,2L).sum( dfac.getONE().multiply(I) );  // x^2 + i
200
201        //b = X.subtract( dfac.getONE().multiply( I ) ); // x - i
202        b = X.subtract(dfac.getONE().multiply(I.negate())); // x + i
203        c = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(3)))); // x - 3i
204        d = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(4)))); // x - 4i
205        e = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(5)))); // x - 5i
206
207        a = b.multiply(c).multiply(d).multiply(e);
208        //System.out.println("a = " + a.toScript());
209        //System.out.println("i = " + cfac.getIMAG());
210
211        Complex<BigRational> Mb = cr.rootBound(a);
212        BigRational M = Mb.getRe();
213        //System.out.println("M = " + M);
214
215        BigRational minf = M.negate(); // - infinity
216        BigRational pinf = M; // + infinity
217        GenPolynomialRing<BigRational> fac = new GenPolynomialRing<BigRational>(pinf, dfac);
218
219        GenPolynomial<BigRational> f = PolyUtil.<BigRational> realPartFromComplex(fac, a);
220        GenPolynomial<BigRational> g = PolyUtil.<BigRational> imaginaryPartFromComplex(fac, a);
221        //System.out.println("re(a) = " + f.toScript());
222        //System.out.println("im(a) = " + g.toScript());
223
224        long[] ri = cr.indexOfRouth(minf, pinf, f, g);
225        //System.out.println("ri = [" + ri[0] + ", " + ri[1] + " ]");
226        long deg = ri[0] + ri[1];
227        assertTrue("sum(ri) == deg(a) ", deg >= a.degree(0));
228    }
229
230
231    /**
232     * Test winding number.
233     * 
234     */
235    @SuppressWarnings("unchecked")
236    public void testWindingNumber() {
237        ComplexRootsSturm<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
238        //Complex<BigRational> I = cfac.getIMAG();
239
240        a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1
241        //a = dfac.random(kl, ll, el, q);
242        //a = dfac.univariate(0,2L).subtract(cfac.getONE());  // x^2 - 1
243        //a = dfac.univariate(0,2L).subtract(I);  // x^2 - I
244        //a = dfac.univariate(0,1L);  // x
245        //System.out.println("a = " + a);
246
247        Complex<BigRational> Mb = cr.rootBound(a);
248        BigRational M = Mb.getRe();
249        //System.out.println("M = " + M);
250        BigRational eps = new BigRational(1, 1000);
251        //System.out.println("eps = " + eps);
252
253        Complex<BigRational>[] corner = new Complex[4];
254
255        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
256        corner[1] = new Complex<BigRational>(cfac, M.negate(), M.negate()); // sw
257        corner[2] = new Complex<BigRational>(cfac, M, M.negate()); // se
258        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
259
260        long v = 0;
261        try {
262            v = cr.windingNumber(new Rectangle<BigRational>(corner), a);
263        } catch (InvalidBoundaryException e) {
264            fail("" + e);
265        }
266        //System.out.println("winding number = " + v);
267        assertTrue("wind(rect,a) == 2 ", v == 2);
268
269        //if ( true ) return;
270
271        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
272        corner[1] = new Complex<BigRational>(cfac, M.negate(), eps); // sw
273        corner[2] = new Complex<BigRational>(cfac, M, eps); // se
274        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
275
276        try {
277            v = cr.windingNumber(new Rectangle<BigRational>(corner), a);
278        } catch (InvalidBoundaryException e) {
279            fail("" + e);
280        }
281        //System.out.println("winding number = " + v);
282        assertTrue("wind(rect,a) == 1 ", v == 1);
283
284        corner[0] = new Complex<BigRational>(cfac, eps.negate(), eps); // nw
285        corner[1] = new Complex<BigRational>(cfac, eps.negate(), eps.negate()); // sw
286        corner[2] = new Complex<BigRational>(cfac, eps, eps.negate()); // se
287        corner[3] = new Complex<BigRational>(cfac, eps, eps); // ne
288
289        try {
290            v = cr.windingNumber(new Rectangle<BigRational>(corner), a);
291        } catch (InvalidBoundaryException e) {
292            fail("" + e);
293        }
294        //System.out.println("winding number = " + v);
295        assertTrue("wind(rect,a) == 0 ", v == 0);
296    }
297
298
299    /**
300     * Test complex roots, sqrt(-1).
301     * 
302     */
303    @SuppressWarnings("unchecked")
304    public void testComplexRootsImag() {
305        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
306        //Complex<BigRational> I = cfac.getIMAG();
307
308        a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1
309        //a = dfac.univariate(0,2L).subtract(cfac.getONE());  // x^2 - 1
310        //a = dfac.univariate(0,2L).subtract(I);  // x^2 - I
311        //a = dfac.univariate(0,1L);  // x
312        //System.out.println("a = " + a);
313
314        Complex<BigRational> Mb = cr.rootBound(a);
315        BigRational M = Mb.getRe();
316        //System.out.println("M = " + M);
317
318        Complex<BigRational>[] corner = new Complex[4];
319
320        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
321        corner[1] = new Complex<BigRational>(cfac, M.negate(), M.negate()); // sw
322        corner[2] = new Complex<BigRational>(cfac, M, M.negate()); // se
323        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
324
325        Rectangle<BigRational> rect = new Rectangle<BigRational>(corner);
326
327        List<Rectangle<BigRational>> roots = null;
328        try {
329            roots = cr.complexRoots(rect, a);
330        } catch (InvalidBoundaryException e) {
331            fail("" + e);
332        }
333        //System.out.println("roots = " + roots);
334        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
335    }
336
337
338    /**
339     * Test complex roots.
340     */
341    @SuppressWarnings("unchecked")
342    public void testComplexRootsRand() {
343        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
344        //Complex<BigRational> I = cfac.getIMAG();
345
346        a = dfac.random(kl, ll, el, q);
347        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
348                        .<Complex<BigRational>> getImplementation(cfac);
349        a = engine.squarefreePart(a);
350
351        //a = dfac.univariate(0,2L).subtract(cfac.getONE());  // x^2 - 1
352        //a = dfac.univariate(0,2L).sum(cfac.fromInteger(1));  // x^2 + 1
353        //a = dfac.univariate(0,2L).subtract(I);  // x^2 - I
354        //a = dfac.univariate(0,1L);  // x
355        //System.out.println("a = " + a);
356
357        Complex<BigRational> Mb = cr.rootBound(a);
358        BigRational M = Mb.getRe();
359        //System.out.println("M = " + M);
360
361        Complex<BigRational>[] corner = new Complex[4];
362
363        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
364        corner[1] = new Complex<BigRational>(cfac, M.negate(), M.negate()); // sw
365        corner[2] = new Complex<BigRational>(cfac, M, M.negate()); // se
366        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
367
368        Rectangle<BigRational> rect = new Rectangle<BigRational>(corner);
369
370
371        List<Rectangle<BigRational>> roots = null;
372        try {
373            roots = cr.complexRoots(rect, a);
374        } catch (InvalidBoundaryException e) {
375            fail("" + e);
376        }
377        //System.out.println("a = " + a);
378        //System.out.println("roots = " + roots);
379        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
380    }
381
382
383    /**
384     * Test complex roots.
385     */
386    public void testComplexRoots() {
387        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
388
389        a = dfac.random(kl, ll, el + 1, q);
390        //System.out.println("a = " + a);
391
392        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
393        //System.out.println("a = " + a);
394        //System.out.println("roots = " + roots);
395        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
396    }
397
398
399    /**
400     * Test complex root refinement.
401     */
402    public void testComplexRootRefinement() {
403        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
404
405        a = dfac.random(kl, ll, el - 1, q);
406        //a = dfac.parse("( (x-1)^3 )");
407        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
408                        .<Complex<BigRational>> getImplementation(cfac);
409        //System.out.println("a = " + a);
410        a = engine.squarefreePart(a);
411        //System.out.println("a = " + a);
412
413        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
414        //System.out.println("a = " + a);
415        //System.out.println("roots = " + roots);
416        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
417
418        BigRational len = new BigRational(1, 1000);
419        //System.out.println("len = " + len);
420
421        for (Rectangle<BigRational> root : roots) {
422            try {
423                Rectangle<BigRational> refine = cr.complexRootRefinement(root, a, len);
424                //System.out.println("refine = " + refine);
425                assertFalse("refine != null", refine == null);
426            } catch (InvalidBoundaryException e) {
427                fail("" + e);
428            }
429        }
430    }
431
432
433    /**
434     * Test complex root refinement full.
435     */
436    public void testComplexRootRefinementFull() {
437        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
438
439        a = dfac.random(kl, ll, el - 1, q);
440        //a = dfac.parse("( (x-1)^3 )");
441        //a = dfac.parse("( x^4-2 )");
442        //System.out.println("a = " + a);
443
444        BigRational len = new BigRational(1, 1000);
445        //System.out.println("len = " + len);
446
447        List<Rectangle<BigRational>> refine = cr.complexRoots(a, len);
448        //System.out.println("refine = " + refine);
449        assertTrue("#roots == deg(a) ", refine.size() == a.degree(0));
450    }
451
452
453    /**
454     * Test winding number with wrong precondition.
455     */
456    @SuppressWarnings("unchecked")
457    public void testWindingNumberWrong() {
458        ComplexRootsSturm<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
459        //Complex<BigRational> I = cfac.getIMAG();
460
461        a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1
462        //a = dfac.random(kl, ll, el, q);
463        //a = dfac.univariate(0,2L).subtract(cfac.getONE());  // x^2 - 1
464        //a = dfac.univariate(0,2L).subtract(I);  // x^2 - I
465        //a = dfac.univariate(0,1L);  // x
466        //System.out.println("a = " + a);
467
468        Complex<BigRational> Mb = cfac.fromInteger(1); //.divide(cfac.fromInteger(2)); //cr.rootBound(a);
469        BigRational M = Mb.getRe();
470        //System.out.println("M = " + M);
471        //BigRational eps = new BigRational(1, 1000);
472        //System.out.println("eps = " + eps);
473        BigRational zero = new BigRational();
474        //BigRational one = new BigRational(1);
475
476        Complex<BigRational>[] corner = new Complex[4];
477
478        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
479        corner[1] = new Complex<BigRational>(cfac, M.negate(), zero); // sw
480        corner[2] = new Complex<BigRational>(cfac, M, zero); // se
481        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
482
483        Rectangle<BigRational> rect = new Rectangle<BigRational>(corner);
484        //System.out.println("rect = " + rect);
485
486        try {
487            long v = cr.windingNumber(rect, a);
488            System.out.println("winding number = " + v);
489            fail("wind(rect,a) must throw an exception");
490        } catch (InvalidBoundaryException e) {
491        }
492    }
493
494
495    /**
496     * Test complex root approximation.
497     */
498    public void testComplexRootApproximation() {
499        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
500
501        //a = dfac.random(kl, ll, el-1, q);
502        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )");
503        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )");
504        //a = dfac.parse("( (x-2)*( x^4-2 ) )");
505        a = dfac.parse("( ( x^4-2 ) )");
506        b = dfac.parse("( (x-1)*(x-2)*(x-3) )");
507        c = dfac.parse("( x^4-2 )");
508        d = dfac.parse("( (x - { 0i1 })*(x-5) )");
509        //a = c; // b; //.multiply(c); //.multiply(d);
510        //System.out.println("a = " + a);
511        //System.out.println("b = " + b);
512        //System.out.println("c = " + c);
513        //System.out.println("d = " + d);
514        //a = b.multiply(c).multiply(d);
515        //System.out.println("a = " + a);
516        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
517                        .<Complex<BigRational>> getImplementation(cfac);
518        a = engine.squarefreePart(a);
519        //System.out.println("a = " + a);
520
521        eps = eps.multiply(new BigRational(1000000));
522        //System.out.println("eps = " + eps);
523        //BigDecimal eps1 = new BigDecimal(eps);
524        //BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
525        //System.out.println("eps1 = " + eps1);
526        //System.out.println("eps2 = " + eps2);
527
528        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
529        //System.out.println("a = " + a);
530        //System.out.println("roots = " + roots);
531        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
532
533        for (Rectangle<BigRational> root : roots) {
534            try {
535                Complex<BigDecimal> cd = cr.approximateRoot(root, a, eps);
536                //System.out.println("cd = " + cd);
537                assertFalse("cd != 0", cd.isZERO());
538            } catch (NoConvergenceException e) {
539                //fail("" + e);
540            }
541        }
542    }
543
544
545    /**
546     * Test complex root approximation full algorithm.
547     */
548    public void testComplexRootApproximationFull() {
549        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
550
551        //a = dfac.random(kl, ll, el-1, q);
552        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )");
553        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )");
554        a = dfac.parse("( (x-2)*( x^4-2 ) )");
555        //a = dfac.parse("( ( x^4-2 ) )");
556        b = dfac.parse("( (x-1)*(x-2)*(x-3) )");
557        c = dfac.parse("( x^4-2 )");
558        d = dfac.parse("( (x - { 0i1 })*(x-5) )");
559        //a = c; // b; //.multiply(c); //.multiply(d);
560        //System.out.println("a = " + a);
561        //System.out.println("b = " + b);
562        //System.out.println("c = " + c);
563        //System.out.println("d = " + d);
564        //a = b.multiply(c).multiply(d);
565        //System.out.println("a = " + a);
566
567        eps = eps.multiply(new BigRational(1000000));
568        //System.out.println("eps = " + eps);
569        //BigDecimal eps1 = new BigDecimal(eps);
570        //BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
571        //System.out.println("eps1 = " + eps1);
572        //System.out.println("eps2 = " + eps2);
573
574        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
575        //System.out.println("a = " + a);
576        //System.out.println("roots = " + roots);
577        //now always true: 
578        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
579    }
580
581
582    /**
583     * Test complex root approximation full algorithm with Wilkinson
584     * polynomials. p = (x-i0)*(x-i1)*(x-i2)*(x-i3*...*(x-in)
585     */
586    public void testComplexRootApproximationWilkinsonFull() {
587        final int N = 4;
588        d = dfac.getONE();
589        e = dfac.univariate(0);
590
591        BigDecimal br = new BigDecimal();
592        ComplexRing<BigDecimal> cf = new ComplexRing<BigDecimal>(br);
593        Complex<BigDecimal> I = cf.getIMAG();
594        Complex<BigDecimal> cc = null;
595        Complex<BigRational> Ir = cfac.getIMAG();
596
597        List<Complex<BigDecimal>> Rn = new ArrayList<Complex<BigDecimal>>(N);
598        a = d;
599        for (int i = 0; i < N; i++) {
600            cc = cf.fromInteger(i).multiply(I);
601            Rn.add(cc);
602            c = dfac.fromInteger(i).multiply(Ir);
603            b = e.subtract(c);
604            a = a.multiply(b);
605        }
606        //System.out.println("a = " + a);
607        Collections.reverse(Rn);
608        //System.out.println("Rn = " + Rn);
609
610        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
611
612        eps = eps.multiply(new BigRational(100000));
613        //System.out.println("eps = " + eps);
614        BigDecimal eps1 = new BigDecimal(eps);
615        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
616        //System.out.println("eps1 = " + eps1);
617        //System.out.println("eps2 = " + eps2);
618
619        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
620        //System.out.println("a = " + a);
621        //System.out.println("roots = " + roots);
622        //now always true: 
623        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
624
625        int i = 0;
626        for (Complex<BigDecimal> dd : roots) {
627            Complex<BigDecimal> di = Rn.get(i++);
628            //System.out.print("di = " + di + ", ");
629            //System.out.println("dd = " + dd);
630            assertTrue("|dd - di| < eps ", dd.subtract(di).norm().getRe().compareTo(eps2) <= 0);
631        }
632    }
633
634
635    /**
636     * Test complex root approximation full algorithm with Wilkinson
637     * polynomials, inverse roots. p = (x-1/i1)*(x-1/i2)*(x-1/i3*...*(x-1/in)
638     */
639    public void testComplexRootApproximationWilkinsonInverseFull() {
640        final int N = 5;
641        d = dfac.getONE();
642        e = dfac.univariate(0);
643
644        BigDecimal br = new BigDecimal();
645        ComplexRing<BigDecimal> cf = new ComplexRing<BigDecimal>(br);
646        Complex<BigDecimal> I = cf.getIMAG();
647        Complex<BigDecimal> cc = null;
648        Complex<BigRational> Ir = cfac.getIMAG();
649
650        List<Complex<BigDecimal>> Rn = new ArrayList<Complex<BigDecimal>>(N);
651        a = d;
652        for (int i = 1; i < N; i++) {
653            cc = cf.fromInteger(i).multiply(I);
654            cc = cc.inverse();
655            Rn.add(cc);
656            c = dfac.fromInteger(i).multiply(Ir);
657            c = d.divide(c);
658            b = e.subtract(c);
659            a = a.multiply(b);
660        }
661        //System.out.println("a = " + a);
662        //Collections.sort(Rn);
663        //System.out.println("Rn = " + Rn);
664
665        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
666
667        eps = eps.multiply(new BigRational(100000));
668        //System.out.println("eps = " + eps);
669        BigDecimal eps1 = new BigDecimal(eps);
670        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
671        //System.out.println("eps1 = " + eps1);
672        //System.out.println("eps2 = " + eps2);
673
674        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
675        //System.out.println("a = " + a);
676        //System.out.println("roots = " + roots);
677        //now always true: 
678        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
679        //Collections.sort(roots);
680        //System.out.println("roots = " + roots);
681
682        for (Complex<BigDecimal> dd : roots) {
683            //System.out.println("dd = " + dd);
684            boolean t = false;
685            for (Complex<BigDecimal> di : Rn) {
686                //System.out.println("di = " + di);
687                t = dd.subtract(di).norm().getRe().compareTo(eps2) <= 0;
688                if (t) {
689                    break;
690                }
691            }
692            if (!t) {
693                //assertTrue("|dd - di| < eps ", dd.subtract(di).norm().getRe().compareTo(eps2) <= 0);
694                fail("|dd - di| < eps ");
695            }
696        }
697    }
698
699
700    /**
701     * Test complex root invariant rectangle.
702     */
703    public void testComplexRootInvariant() {
704        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
705
706        a = dfac.random(kl, ll, el - 1, q);
707        b = dfac.random(kl, ll, 2, q);
708        //a = dfac.parse("( (x-1)^3 )");
709        //a = dfac.parse("( x^4-2 )");
710        if (a.degree() == 0) {
711            return;
712        }
713        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
714                        .<Complex<BigRational>> getImplementation(cfac);
715        a = engine.squarefreePart(a);
716        b = engine.squarefreePart(b);
717        //System.out.println("a = " + a);
718        //System.out.println("b = " + b);
719
720        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
721        //System.out.println("roots = " + roots);
722        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
723
724        Rectangle<BigRational> rect = roots.get(0);
725        //System.out.println("rect = " + rect);
726
727        try {
728            Rectangle<BigRational> ref = cr.invariantRectangle(rect, a, b);
729            //System.out.println("rect = " + rect);
730            //System.out.println("ref  = " + ref);
731            assertTrue("rect subseteq ref ", rect.contains(ref));
732        } catch (InvalidBoundaryException e) {
733            e.printStackTrace();
734            fail("bad boundary");
735        }
736    }
737
738
739    /**
740     * Test complex root invariant magnitude rectangle.
741     */
742    public void testComplexRootInvariantMagnitude() {
743        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
744
745        a = dfac.random(kl, ll, el - 1, q);
746        b = dfac.random(kl, ll, 3, q);
747        //a = dfac.parse("( x^2 + 1 )");
748        //b = dfac.parse("( x - 0i1 )");
749        if (a.degree() == 0) {
750            return;
751        }
752        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
753                        .<Complex<BigRational>> getImplementation(cfac);
754        a = engine.squarefreePart(a);
755        b = engine.squarefreePart(b);
756        //System.out.println("a = " + a);
757        //System.out.println("b = " + b);
758
759        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
760        //System.out.println("roots = " + roots);
761        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
762
763        Rectangle<BigRational> rect = roots.get(0);
764        //System.out.println("rect = " + rect);
765
766        try {
767            Rectangle<BigRational> ref = cr.invariantMagnitudeRectangle(rect, a, b, eps);
768            //System.out.println("ref = " + ref);
769            assertTrue("rect subseteq ref ", rect.contains(ref));
770            Complex<BigRational> mag = cr.complexRectangleMagnitude(ref, a, b);
771            //System.out.println("mag  = " + mag);
772            Complex<BigRational> cmag = cr.complexMagnitude(ref, a, b, eps);
773            //System.out.println("cmag = " + cmag);
774            assertEquals("mag == cmag: " + cmag, mag, cmag);
775            //BigRational rmag = cmag.getRe();
776            //System.out.println("rmag = " + new BigDecimal(cmag.getRe()) + " i " + new BigDecimal(cmag.getIm()));
777        } catch (InvalidBoundaryException e) {
778            e.printStackTrace();
779            fail("bad boundary");
780        }
781    }
782
783}