001/*
002 * $Id$
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import edu.jas.arith.BigDecimal;
013import edu.jas.arith.BigRational;
014import edu.jas.kern.ComputerThreads;
015import edu.jas.poly.Complex;
016import edu.jas.poly.ComplexRing;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019import edu.jas.poly.PolyUtil;
020import edu.jas.poly.TermOrder;
021import edu.jas.structure.Power;
022import edu.jas.ufd.Squarefree;
023import edu.jas.ufd.SquarefreeFactory;
024
025import junit.framework.Test;
026import junit.framework.TestCase;
027import junit.framework.TestSuite;
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        long deg = a.degree(0); // now fixed
392
393        Squarefree<Complex<BigRational>> engine = SquarefreeFactory.<Complex<BigRational>> getImplementation(cfac);
394        b = engine.squarefreePart(a);
395        //long deg = b.degree(0); // multiplicity is fixed
396
397        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
398        //System.out.println("a = " + a);
399        //System.out.println("roots = " + roots);
400        //assertTrue("#roots == deg(a) " + (a.degree()-roots.size()), roots.size() == a.degree(0));
401        assertTrue("#roots == deg(a): " + roots + ", " + a + ", " + b, roots.size() == deg);
402    }
403
404
405    /**
406     * Test complex root refinement.
407     */
408    public void testComplexRootRefinement() {
409        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
410
411        a = dfac.random(kl, ll, el - 1, q);
412        //a = dfac.parse("( (x-1)^3 )");
413        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
414                        .<Complex<BigRational>> getImplementation(cfac);
415        //System.out.println("a = " + a);
416        a = engine.squarefreePart(a);
417        //System.out.println("a = " + a);
418
419        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
420        //System.out.println("a = " + a);
421        //System.out.println("roots = " + roots);
422        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
423
424        BigRational len = new BigRational(1, 1000);
425        //System.out.println("len = " + len);
426
427        for (Rectangle<BigRational> root : roots) {
428            try {
429                Rectangle<BigRational> refine = cr.complexRootRefinement(root, a, len);
430                //System.out.println("refine = " + refine);
431                assertFalse("refine != null", refine == null);
432            } catch (InvalidBoundaryException e) {
433                fail("" + e);
434            }
435        }
436    }
437
438
439    /**
440     * Test complex root refinement full.
441     */
442    public void testComplexRootRefinementFull() {
443        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
444
445        a = dfac.random(kl, ll, el - 1, q);
446        //a = dfac.parse("( (x-1)^3 )");
447        //a = dfac.parse("( x^4-2 )");
448        //System.out.println("a = " + a);
449
450        BigRational len = new BigRational(1, 1000);
451        //System.out.println("len = " + len);
452
453        List<Rectangle<BigRational>> refine = cr.complexRoots(a, len);
454        //System.out.println("refine = " + refine);
455        assertTrue("#roots == deg(a) ", refine.size() == a.degree(0));
456    }
457
458
459    /**
460     * Test winding number with wrong precondition.
461     */
462    @SuppressWarnings("unchecked")
463    public void testWindingNumberWrong() {
464        ComplexRootsSturm<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
465        //Complex<BigRational> I = cfac.getIMAG();
466
467        a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1
468        //a = dfac.random(kl, ll, el, q);
469        //a = dfac.univariate(0,2L).subtract(cfac.getONE());  // x^2 - 1
470        //a = dfac.univariate(0,2L).subtract(I);  // x^2 - I
471        //a = dfac.univariate(0,1L);  // x
472        //System.out.println("a = " + a);
473
474        Complex<BigRational> Mb = cfac.fromInteger(1); //.divide(cfac.fromInteger(2)); //cr.rootBound(a);
475        BigRational M = Mb.getRe();
476        //System.out.println("M = " + M);
477        //BigRational eps = new BigRational(1, 1000);
478        //System.out.println("eps = " + eps);
479        BigRational zero = new BigRational();
480        //BigRational one = new BigRational(1);
481
482        Complex<BigRational>[] corner = new Complex[4];
483
484        corner[0] = new Complex<BigRational>(cfac, M.negate(), M); // nw
485        corner[1] = new Complex<BigRational>(cfac, M.negate(), zero); // sw
486        corner[2] = new Complex<BigRational>(cfac, M, zero); // se
487        corner[3] = new Complex<BigRational>(cfac, M, M); // ne
488
489        Rectangle<BigRational> rect = new Rectangle<BigRational>(corner);
490        //System.out.println("rect = " + rect);
491
492        try {
493            long v = cr.windingNumber(rect, a);
494            System.out.println("winding number = " + v);
495            fail("wind(rect,a) must throw an exception");
496        } catch (InvalidBoundaryException e) {
497        }
498    }
499
500
501    /**
502     * Test complex root approximation.
503     */
504    public void testComplexRootApproximation() {
505        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
506
507        //a = dfac.random(kl, ll, el-1, q);
508        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )");
509        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )");
510        //a = dfac.parse("( (x-2)*( x^4-2 ) )");
511        a = dfac.parse("( ( x^4-2 ) )");
512        b = dfac.parse("( (x-1)*(x-2)*(x-3) )");
513        c = dfac.parse("( x^4-2 )");
514        d = dfac.parse("( (x - { 0i1 })*(x-5) )");
515        //a = c; // b; //.multiply(c); //.multiply(d);
516        //System.out.println("a = " + a);
517        //System.out.println("b = " + b);
518        //System.out.println("c = " + c);
519        //System.out.println("d = " + d);
520        //a = b.multiply(c).multiply(d);
521        //System.out.println("a = " + a);
522        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
523                        .<Complex<BigRational>> getImplementation(cfac);
524        a = engine.squarefreePart(a);
525        //System.out.println("a = " + a);
526
527        eps = eps.multiply(new BigRational(1000000));
528        //System.out.println("eps = " + eps);
529        //BigDecimal eps1 = new BigDecimal(eps);
530        //BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
531        //System.out.println("eps1 = " + eps1);
532        //System.out.println("eps2 = " + eps2);
533
534        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
535        //System.out.println("a = " + a);
536        //System.out.println("roots = " + roots);
537        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
538
539        for (Rectangle<BigRational> root : roots) {
540            try {
541                Complex<BigDecimal> cd = cr.approximateRoot(root, a, eps);
542                //System.out.println("cd = " + cd);
543                assertFalse("cd != 0", cd.isZERO());
544            } catch (NoConvergenceException e) {
545                //fail("" + e);
546            }
547        }
548    }
549
550
551    /**
552     * Test complex root approximation full algorithm.
553     */
554    public void testComplexRootApproximationFull() {
555        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
556
557        //a = dfac.random(kl, ll, el-1, q);
558        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )");
559        //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )");
560        a = dfac.parse("( (x-2)*( x^4-2 ) )");
561        //a = dfac.parse("( ( x^4-2 ) )");
562        b = dfac.parse("( (x-1)*(x-2)*(x-3) )");
563        c = dfac.parse("( x^4-2 )");
564        d = dfac.parse("( (x - { 0i1 })*(x-5) )");
565        //a = c; // b; //.multiply(c); //.multiply(d);
566        //System.out.println("a = " + a);
567        //System.out.println("b = " + b);
568        //System.out.println("c = " + c);
569        //System.out.println("d = " + d);
570        //a = b.multiply(c).multiply(d);
571        //System.out.println("a = " + a);
572
573        eps = eps.multiply(new BigRational(1000000));
574        //System.out.println("eps = " + eps);
575        //BigDecimal eps1 = new BigDecimal(eps);
576        //BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
577        //System.out.println("eps1 = " + eps1);
578        //System.out.println("eps2 = " + eps2);
579
580        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
581        //System.out.println("a = " + a);
582        //System.out.println("roots = " + roots);
583        //now always true: 
584        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
585    }
586
587
588    /**
589     * Test complex root approximation full algorithm with Wilkinson
590     * polynomials. p = (x-i0)*(x-i1)*(x-i2)*(x-i3*...*(x-in)
591     */
592    public void testComplexRootApproximationWilkinsonFull() {
593        final int N = 4;
594        d = dfac.getONE();
595        e = dfac.univariate(0);
596
597        BigDecimal br = new BigDecimal();
598        ComplexRing<BigDecimal> cf = new ComplexRing<BigDecimal>(br);
599        Complex<BigDecimal> I = cf.getIMAG();
600        Complex<BigDecimal> cc = null;
601        Complex<BigRational> Ir = cfac.getIMAG();
602
603        List<Complex<BigDecimal>> Rn = new ArrayList<Complex<BigDecimal>>(N);
604        a = d;
605        for (int i = 0; i < N; i++) {
606            cc = cf.fromInteger(i).multiply(I);
607            Rn.add(cc);
608            c = dfac.fromInteger(i).multiply(Ir);
609            b = e.subtract(c);
610            a = a.multiply(b);
611        }
612        //System.out.println("a = " + a);
613        Collections.reverse(Rn);
614        //System.out.println("Rn = " + Rn);
615        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
616
617        eps = eps.multiply(new BigRational(100000));
618        //System.out.println("eps = " + eps);
619        BigDecimal eps1 = new BigDecimal(eps);
620        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
621        //System.out.println("eps1 = " + eps1);
622        //System.out.println("eps2 = " + eps2);
623
624        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
625        // fix ordering of roots
626        cc = roots.remove(0);
627        roots.add(cc);
628        //System.out.println("a =     " + a);
629        //System.out.println("roots = " + roots);
630        //System.out.println("Rn =    " + Rn);
631        //now always true: 
632        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
633
634        int i = 0;
635        for (Complex<BigDecimal> dd : roots) {
636            Complex<BigDecimal> di = Rn.get(i++);
637            //System.out.print("di = " + di + ", ");
638            //System.out.println("di = " + di + ", " + "dd = " + dd);
639            Complex<BigDecimal> d = dd.subtract(di).norm();
640            assertTrue("|dd - di| < eps: " + d + ", " + dd + ", " + di, d.getRe().compareTo(eps2) <= 0);
641        }
642    }
643
644
645    /**
646     * Test complex root approximation full algorithm with Wilkinson
647     * polynomials, inverse roots. p = (x-1/i1)*(x-1/i2)*(x-1/i3*...*(x-1/in)
648     */
649    public void testComplexRootApproximationWilkinsonInverseFull() {
650        final int N = 5;
651        d = dfac.getONE();
652        e = dfac.univariate(0);
653
654        BigDecimal br = new BigDecimal();
655        ComplexRing<BigDecimal> cf = new ComplexRing<BigDecimal>(br);
656        Complex<BigDecimal> I = cf.getIMAG();
657        Complex<BigDecimal> cc = null;
658        Complex<BigRational> Ir = cfac.getIMAG();
659
660        List<Complex<BigDecimal>> Rn = new ArrayList<Complex<BigDecimal>>(N);
661        a = d;
662        for (int i = 1; i < N; i++) {
663            cc = cf.fromInteger(i).multiply(I);
664            cc = cc.inverse();
665            Rn.add(cc);
666            c = dfac.fromInteger(i).multiply(Ir);
667            c = d.divide(c);
668            b = e.subtract(c);
669            a = a.multiply(b);
670        }
671        //System.out.println("a = " + a);
672        //Collections.sort(Rn);
673        //System.out.println("Rn = " + Rn);
674
675        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
676
677        eps = eps.multiply(new BigRational(100000));
678        //System.out.println("eps = " + eps);
679        BigDecimal eps1 = new BigDecimal(eps);
680        BigDecimal eps2 = eps1.multiply(new BigDecimal("10"));
681        //System.out.println("eps1 = " + eps1);
682        //System.out.println("eps2 = " + eps2);
683
684        List<Complex<BigDecimal>> roots = cr.approximateRoots(a, eps);
685        //System.out.println("a = " + a);
686        //System.out.println("roots = " + roots);
687        //now always true: 
688        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
689        //Collections.sort(roots);
690        //System.out.println("roots = " + roots);
691
692        for (Complex<BigDecimal> dd : roots) {
693            //System.out.println("dd = " + dd);
694            boolean t = false;
695            for (Complex<BigDecimal> di : Rn) {
696                //System.out.println("di = " + di);
697                t = dd.subtract(di).norm().getRe().compareTo(eps2) <= 0;
698                if (t) {
699                    break;
700                }
701            }
702            if (!t) {
703                //assertTrue("|dd - di| < eps ", dd.subtract(di).norm().getRe().compareTo(eps2) <= 0);
704                fail("|dd - di| < eps ");
705            }
706        }
707    }
708
709
710    /**
711     * Test complex root invariant rectangle.
712     */
713    public void testComplexRootInvariant() {
714        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
715
716        a = dfac.random(kl, ll, el - 1, q);
717        b = dfac.random(kl, ll, 2, q);
718        //a = dfac.parse("( (x-1)^3 )");
719        //a = dfac.parse("( x^4-2 )");
720        if (a.degree() == 0) {
721            return;
722        }
723        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
724                        .<Complex<BigRational>> getImplementation(cfac);
725        a = engine.squarefreePart(a);
726        b = engine.squarefreePart(b);
727        //System.out.println("a = " + a);
728        //System.out.println("b = " + b);
729
730        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
731        //System.out.println("roots = " + roots);
732        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
733
734        Rectangle<BigRational> rect = roots.get(0);
735        //System.out.println("rect = " + rect);
736
737        try {
738            Rectangle<BigRational> ref = cr.invariantRectangle(rect, a, b);
739            //System.out.println("rect = " + rect);
740            //System.out.println("ref  = " + ref);
741            assertTrue("rect subseteq ref ", rect.contains(ref));
742        } catch (InvalidBoundaryException e) {
743            e.printStackTrace();
744            fail("bad boundary");
745        }
746    }
747
748
749    /**
750     * Test complex root invariant magnitude rectangle.
751     */
752    public void testComplexRootInvariantMagnitude() {
753        ComplexRootsAbstract<BigRational> cr = new ComplexRootsSturm<BigRational>(cfac);
754
755        a = dfac.random(kl, ll, el - 1, q);
756        b = dfac.random(kl, ll, 3, q);
757        //a = dfac.parse("( x^2 + 1 )");
758        //b = dfac.parse("( x - 0i1 )");
759        if (a.degree() == 0) {
760            return;
761        }
762        Squarefree<Complex<BigRational>> engine = SquarefreeFactory
763                        .<Complex<BigRational>> getImplementation(cfac);
764        a = engine.squarefreePart(a);
765        b = engine.squarefreePart(b);
766        //System.out.println("a = " + a);
767        //System.out.println("b = " + b);
768
769        List<Rectangle<BigRational>> roots = cr.complexRoots(a);
770        //System.out.println("roots = " + roots);
771        assertTrue("#roots == deg(a) ", roots.size() == a.degree(0));
772
773        Rectangle<BigRational> rect = roots.get(0);
774        //System.out.println("rect = " + rect);
775
776        try {
777            Rectangle<BigRational> ref = cr.invariantMagnitudeRectangle(rect, a, b, eps);
778            //System.out.println("ref = " + ref);
779            assertTrue("rect subseteq ref ", rect.contains(ref));
780            Complex<BigRational> mag = cr.complexRectangleMagnitude(ref, a, b);
781            //System.out.println("mag  = " + mag);
782            Complex<BigRational> cmag = cr.complexMagnitude(ref, a, b, eps);
783            //System.out.println("cmag = " + cmag);
784            assertEquals("mag == cmag: " + cmag, mag, cmag);
785            //BigRational rmag = cmag.getRe();
786            //System.out.println("rmag = " + new BigDecimal(cmag.getRe()) + " i " + new BigDecimal(cmag.getIm()));
787        } catch (InvalidBoundaryException e) {
788            e.printStackTrace();
789            fail("bad boundary");
790        }
791    }
792
793}