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}