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