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