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}