001/* 002 * $Id: RootFactory.java 5828 2018-05-13 15:52:01Z kredel $ 003 */ 004 005package edu.jas.root; 006 007 008import java.util.ArrayList; 009import java.util.LinkedList; 010import java.util.List; 011import java.util.Map; 012 013import edu.jas.arith.BigDecimal; 014import edu.jas.arith.BigRational; 015import edu.jas.arith.Rational; 016import edu.jas.poly.Complex; 017import edu.jas.poly.ComplexRing; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenPolynomialRing; 020import edu.jas.poly.PolyUtil; 021import edu.jas.structure.GcdRingElem; 022import edu.jas.ufd.FactorAbstract; 023import edu.jas.ufd.FactorFactory; 024import edu.jas.ufd.SquarefreeAbstract; 025import edu.jas.ufd.SquarefreeFactory; 026 027 028/** 029 * Roots factory. Generate real and complex algebraic numbers from root 030 * intervals or rectangles. 031 * @author Heinz Kredel 032 */ 033public class RootFactory { 034 035 036 /** 037 * Is real algebraic number a root of a polynomial. 038 * @param f univariate polynomial. 039 * @param r real algebraic number. 040 * @return true, if f(r) == 0, else false; 041 */ 042 public static <C extends GcdRingElem<C> & Rational> boolean isRoot(GenPolynomial<C> f, 043 RealAlgebraicNumber<C> r) { 044 RealAlgebraicRing<C> rr = r.factory(); 045 GenPolynomialRing<RealAlgebraicNumber<C>> rfac = new GenPolynomialRing<RealAlgebraicNumber<C>>(rr, 046 f.factory()); 047 GenPolynomial<RealAlgebraicNumber<C>> p; 048 p = PolyUtilRoot.<C> convertToRealCoefficients(rfac, f); 049 RealAlgebraicNumber<C> a = PolyUtil.<RealAlgebraicNumber<C>> evaluateMain(rr, p, r); 050 return a.isZERO(); 051 } 052 053 054 /** 055 * Real algebraic numbers. 056 * @param f univariate polynomial. 057 * @return a list of different real algebraic numbers. 058 */ 059 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbers( 060 GenPolynomial<C> f) { 061 RealRoots<C> rr = new RealRootsSturm<C>(); 062 SquarefreeAbstract<C> engine = SquarefreeFactory.<C> getImplementation(f.ring.coFac); 063 Map<GenPolynomial<C>, Long> SF = engine.squarefreeFactors(f); 064 //Set<GenPolynomial<C>> S = SF.keySet(); 065 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 066 for (Map.Entry<GenPolynomial<C>, Long> me : SF.entrySet()) { 067 GenPolynomial<C> sp = me.getKey(); 068 List<Interval<C>> iv = rr.realRoots(sp); 069 for (Interval<C> I : iv) { 070 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I); 071 RealAlgebraicNumber<C> rn = rar.getGenerator(); 072 long mult = me.getValue(); 073 for (int i = 0; i < mult; i++) { 074 list.add(rn); 075 } 076 } 077 } 078 return list; 079 } 080 081 082 /** 083 * Real algebraic numbers. 084 * @param f univariate polynomial. 085 * @param eps rational precision. 086 * @return a list of different real algebraic numbers. 087 */ 088 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbers( 089 GenPolynomial<C> f, BigRational eps) { 090 RealRoots<C> rr = new RealRootsSturm<C>(); 091 SquarefreeAbstract<C> engine = SquarefreeFactory.<C> getImplementation(f.ring.coFac); 092 Map<GenPolynomial<C>, Long> SF = engine.squarefreeFactors(f); 093 //Set<GenPolynomial<C>> S = SF.keySet(); 094 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 095 for (Map.Entry<GenPolynomial<C>, Long> me : SF.entrySet()) { 096 GenPolynomial<C> sp = me.getKey(); 097 List<Interval<C>> iv = rr.realRoots(sp, eps); 098 for (Interval<C> I : iv) { 099 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I); 100 rar.setEps(eps); 101 RealAlgebraicNumber<C> rn = rar.getGenerator(); 102 long mult = me.getValue(); 103 for (int i = 0; i < mult; i++) { 104 list.add(rn); 105 } 106 } 107 } 108 return list; 109 } 110 111 112 /** 113 * Real algebraic numbers from a field. 114 * @param f univariate polynomial. 115 * @return a list of different real algebraic numbers from a field. 116 */ 117 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbersField( 118 GenPolynomial<C> f) { 119 RealRoots<C> rr = new RealRootsSturm<C>(); 120 FactorAbstract<C> engine = FactorFactory.<C> getImplementation(f.ring.coFac); 121 Map<GenPolynomial<C>, Long> SF = engine.baseFactors(f); 122 //Set<GenPolynomial<C>> S = SF.keySet(); 123 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 124 for (Map.Entry<GenPolynomial<C>, Long> me : SF.entrySet()) { 125 GenPolynomial<C> sp = me.getKey(); 126 List<Interval<C>> iv = rr.realRoots(sp); 127 for (Interval<C> I : iv) { 128 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I, true);//field 129 RealAlgebraicNumber<C> rn = rar.getGenerator(); 130 long mult = me.getValue(); 131 for (int i = 0; i < mult; i++) { 132 list.add(rn); 133 } 134 } 135 } 136 return list; 137 } 138 139 140 /** 141 * Real algebraic numbers from a field. 142 * @param f univariate polynomial. 143 * @param eps rational precision. 144 * @return a list of different real algebraic numbers from a field. 145 */ 146 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbersField( 147 GenPolynomial<C> f, BigRational eps) { 148 RealRoots<C> rr = new RealRootsSturm<C>(); 149 FactorAbstract<C> engine = FactorFactory.<C> getImplementation(f.ring.coFac); 150 Map<GenPolynomial<C>, Long> SF = engine.baseFactors(f); 151 //Set<GenPolynomial<C>> S = SF.keySet(); 152 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 153 for (Map.Entry<GenPolynomial<C>, Long> me : SF.entrySet()) { 154 GenPolynomial<C> sp = me.getKey(); 155 List<Interval<C>> iv = rr.realRoots(sp, eps); 156 for (Interval<C> I : iv) { 157 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I, true);//field 158 rar.setEps(eps); 159 RealAlgebraicNumber<C> rn = rar.getGenerator(); 160 long mult = me.getValue(); 161 for (int i = 0; i < mult; i++) { 162 list.add(rn); 163 } 164 } 165 } 166 return list; 167 } 168 169 170 /** 171 * Real algebraic numbers from a irreducible polynomial. 172 * @param f univariate irreducible polynomial. 173 * @return a list of different real algebraic numbers from a field. 174 */ 175 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbersIrred( 176 GenPolynomial<C> f) { 177 RealRoots<C> rr = new RealRootsSturm<C>(); 178 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 179 List<Interval<C>> iv = rr.realRoots(f); 180 for (Interval<C> I : iv) { 181 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(f, I, true);//field 182 RealAlgebraicNumber<C> rn = rar.getGenerator(); 183 list.add(rn); 184 } 185 return list; 186 } 187 188 189 /** 190 * Real algebraic numbers from a irreducible polynomial. 191 * @param f univariate irreducible polynomial. 192 * @param eps rational precision. 193 * @return a list of different real algebraic numbers from a field. 194 */ 195 public static <C extends GcdRingElem<C> & Rational> List<RealAlgebraicNumber<C>> realAlgebraicNumbersIrred( 196 GenPolynomial<C> f, BigRational eps) { 197 RealRoots<C> rr = new RealRootsSturm<C>(); 198 List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>(); 199 List<Interval<C>> iv = rr.realRoots(f, eps); 200 for (Interval<C> I : iv) { 201 RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(f, I, true);//field 202 rar.setEps(eps); 203 RealAlgebraicNumber<C> rn = rar.getGenerator(); 204 list.add(rn); 205 } 206 return list; 207 } 208 209 210 /** 211 * Is complex algebraic number a root of a polynomial. 212 * @param f univariate polynomial. 213 * @param r complex algebraic number. 214 * @return true, if f(r) == 0, else false; 215 */ 216 public static <C extends GcdRingElem<C> & Rational> boolean isRoot(GenPolynomial<C> f, 217 ComplexAlgebraicNumber<C> r) { 218 ComplexAlgebraicRing<C> cr = r.factory(); 219 GenPolynomialRing<ComplexAlgebraicNumber<C>> cfac = new GenPolynomialRing<ComplexAlgebraicNumber<C>>( 220 cr, f.factory()); 221 GenPolynomial<ComplexAlgebraicNumber<C>> p; 222 p = PolyUtilRoot.<C> convertToComplexCoefficients(cfac, f); 223 ComplexAlgebraicNumber<C> a = PolyUtil.<ComplexAlgebraicNumber<C>> evaluateMain(cr, p, r); 224 return a.isZERO(); 225 } 226 227 228 /** 229 * Is complex algebraic number a root of a complex polynomial. 230 * @param f univariate complex polynomial. 231 * @param r complex algebraic number. 232 * @return true, if f(r) == 0, else false; 233 */ 234 public static <C extends GcdRingElem<C> & Rational> boolean isRootComplex(GenPolynomial<Complex<C>> f, 235 ComplexAlgebraicNumber<C> r) { 236 ComplexAlgebraicRing<C> cr = r.factory(); 237 GenPolynomialRing<ComplexAlgebraicNumber<C>> cfac = new GenPolynomialRing<ComplexAlgebraicNumber<C>>( 238 cr, f.factory()); 239 GenPolynomial<ComplexAlgebraicNumber<C>> p; 240 p = PolyUtilRoot.<C> convertToComplexCoefficientsFromComplex(cfac, f); 241 ComplexAlgebraicNumber<C> a = PolyUtil.<ComplexAlgebraicNumber<C>> evaluateMain(cr, p, r); 242 return a.isZERO(); 243 } 244 245 246 /** 247 * Is complex algebraic number a real root of a polynomial. 248 * @param f univariate polynomial. 249 * @param c complex algebraic number. 250 * @param r real algebraic number. 251 * @return true, if f(c) == 0 and c == r, else false; 252 */ 253 public static <C extends GcdRingElem<C> & Rational> boolean isRealRoot(GenPolynomial<C> f, 254 ComplexAlgebraicNumber<C> c, RealAlgebraicNumber<C> r) { 255 boolean t = isRoot(f, c) && isRoot(f, r); 256 if (!t) { 257 return t; 258 } 259 Rectangle<C> rc = c.ring.root; 260 Interval<C> ivci = new Interval<C>(rc.getSW().getIm(), rc.getNE().getIm()); 261 t = ivci.contains(f.ring.coFac.getZERO()); 262 if (!t) { 263 return t; 264 } 265 //System.out.println("imag = 0"); 266 Interval<C> ivc = new Interval<C>(rc.getSW().getRe(), rc.getNE().getRe()); 267 Interval<C> ivr = r.ring.root; 268 // disjoint intervals 269 if (ivc.right.compareTo(ivr.left) < 0 || ivr.right.compareTo(ivc.left) < 0) { 270 //System.out.println("disjoint: ivc = " + ivc + ", ivr = " + ivr); 271 return false; 272 } 273 //System.out.println("not disjoint"); 274 // full containement 275 t = ivc.contains(ivr) || ivr.contains(ivc); 276 if (t) { 277 return t; 278 } 279 //System.out.println("with overlap"); 280 // overlap, refine to smaller interval 281 C left = ivc.left; 282 if (left.compareTo(ivr.left) > 0) { 283 left = ivr.left; 284 } 285 C right = ivc.right; 286 if (right.compareTo(ivr.right) < 0) { 287 right = ivr.right; 288 } 289 Interval<C> ref = new Interval<C>(left, right); 290 //System.out.println("refined interval " + ref); 291 RealRoots<C> reng = r.ring.engine; //new RealRootsSturm<C>(); 292 long z = reng.realRootCount(ref, f); 293 if (z != 1) { 294 return false; 295 } 296 ComplexRing<C> cr = rc.getSW().ring; 297 Complex<C> sw = new Complex<C>(cr, left, rc.getSW().getIm()); 298 Complex<C> ne = new Complex<C>(cr, right, rc.getNE().getIm()); 299 //Complex<C> sw = new Complex<C>(cr, left, cr.ring.getZERO()); 300 //Complex<C> ne = new Complex<C>(cr, right, cr.ring.getZERO()); 301 Rectangle<C> rec = new Rectangle<C>(sw, ne); 302 //System.out.println("refined rectangle " + rec); 303 ComplexRoots<C> ceng = c.ring.engine; //new ComplexRootsSturm<C>(); 304 GenPolynomial<Complex<C>> p = PolyUtilRoot.<C> complexFromAny(f); 305 try { 306 z = ceng.complexRootCount(rec, p); 307 } catch (InvalidBoundaryException e) { 308 System.out.println("should not happen, rec = " + rec + ", p = " + p); 309 e.printStackTrace(); 310 z = 0; 311 } 312 //System.out.println("complexRootCount: " + z); 313 if (z != 1) { 314 return false; 315 } 316 return true; 317 } 318 319 320 /** 321 * Is complex decimal number a real root of a polynomial. 322 * @param f univariate polynomial. 323 * @param c complex decimal number. 324 * @param r real decimal number. 325 * @param eps desired precision. 326 * @return true, if f(c) == 0 and c == r, else false; 327 */ 328 public static <C extends GcdRingElem<C> & Rational> boolean isRealRoot(GenPolynomial<C> f, 329 Complex<BigDecimal> c, BigDecimal r, BigRational eps) { 330 BigDecimal e = new BigDecimal(eps); 331 if (c.getIm().abs().compareTo(e) > 0) { 332 return false; 333 } 334 if (c.getRe().subtract(r).abs().compareTo(e) > 0) { 335 return false; 336 } 337 GenPolynomialRing<Complex<C>> cfac = new GenPolynomialRing<Complex<C>>( 338 new ComplexRing<C>(f.ring.coFac), f.ring); 339 GenPolynomial<Complex<C>> cf = PolyUtil.<C> complexFromAny(cfac, f); 340 ComplexRing<BigDecimal> cd = new ComplexRing<BigDecimal>(e); 341 GenPolynomialRing<Complex<BigDecimal>> rfac = new GenPolynomialRing<Complex<BigDecimal>>(cd, cf.ring); 342 GenPolynomial<Complex<BigDecimal>> cdf = PolyUtil.<C> complexDecimalFromRational(rfac, cf); 343 Complex<BigDecimal> z = PolyUtil.evaluateMain(cd, cdf, c); 344 if (z.isZERO()) { 345 return true; 346 } 347 System.out.println("z != 0: " + z); 348 return false; 349 } 350 351 352 /** 353 * Complex algebraic numbers. 354 * @param f univariate polynomial. 355 * @return a list of different complex algebraic numbers. 356 */ 357 public static <C extends GcdRingElem<C> & Rational> List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex( 358 GenPolynomial<Complex<C>> f) { 359 ComplexRoots<C> cr = new ComplexRootsSturm<C>(f.ring.coFac); 360 SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory 361 .<Complex<C>> getImplementation(f.ring.coFac); 362 Map<GenPolynomial<Complex<C>>, Long> SF = engine.squarefreeFactors(f); 363 //Set<GenPolynomial<Complex<C>>> S = SF.keySet(); 364 List<ComplexAlgebraicNumber<C>> list = new ArrayList<ComplexAlgebraicNumber<C>>(); 365 for (Map.Entry<GenPolynomial<Complex<C>>, Long> me : SF.entrySet()) { 366 GenPolynomial<Complex<C>> sp = me.getKey(); 367 List<Rectangle<C>> iv = cr.complexRoots(sp); 368 for (Rectangle<C> I : iv) { 369 ComplexAlgebraicRing<C> car = new ComplexAlgebraicRing<C>(sp, I); 370 ComplexAlgebraicNumber<C> cn = car.getGenerator(); 371 long mult = me.getValue(); 372 for (int i = 0; i < mult; i++) { 373 list.add(cn); 374 } 375 } 376 } 377 return list; 378 } 379 380 381 /** 382 * Complex algebraic numbers. 383 * @param f univariate polynomial. 384 * @param eps rational precision. 385 * @return a list of different complex algebraic numbers. 386 */ 387 public static <C extends GcdRingElem<C> & Rational> List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex( 388 GenPolynomial<Complex<C>> f, BigRational eps) { 389 ComplexRoots<C> cr = new ComplexRootsSturm<C>(f.ring.coFac); 390 SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory 391 .<Complex<C>> getImplementation(f.ring.coFac); 392 Map<GenPolynomial<Complex<C>>, Long> SF = engine.squarefreeFactors(f); 393 //Set<GenPolynomial<Complex<C>>> S = SF.keySet(); 394 List<ComplexAlgebraicNumber<C>> list = new ArrayList<ComplexAlgebraicNumber<C>>(); 395 for (Map.Entry<GenPolynomial<Complex<C>>, Long> me : SF.entrySet()) { 396 GenPolynomial<Complex<C>> sp = me.getKey(); 397 List<Rectangle<C>> iv = cr.complexRoots(sp); 398 for (Rectangle<C> I : iv) { 399 Rectangle<C> Iv = I; 400 try { 401 Iv = cr.complexRootRefinement(I, sp, eps); 402 } catch (InvalidBoundaryException e) { 403 e.printStackTrace(); 404 } 405 ComplexAlgebraicRing<C> car = new ComplexAlgebraicRing<C>(sp, Iv); 406 car.setEps(eps); 407 ComplexAlgebraicNumber<C> cn = car.getGenerator(); 408 long mult = me.getValue(); 409 for (int i = 0; i < mult; i++) { 410 list.add(cn); 411 } 412 } 413 } 414 return list; 415 } 416 417 418 /** 419 * Complex algebraic numbers. 420 * @param f univariate (rational) polynomial. 421 * @return a list of different complex algebraic numbers. 422 */ 423 public static <C extends GcdRingElem<C> & Rational> List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbers( 424 GenPolynomial<C> f) { 425 GenPolynomial<Complex<C>> fc = PolyUtilRoot.<C> complexFromAny(f); 426 return complexAlgebraicNumbersComplex(fc); 427 } 428 429 430 /** 431 * Complex algebraic numbers. 432 * @param f univariate (rational) polynomial. 433 * @param eps rational precision. 434 * @return a list of different complex algebraic numbers. 435 */ 436 public static <C extends GcdRingElem<C> & Rational> List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbers( 437 GenPolynomial<C> f, BigRational eps) { 438 GenPolynomial<Complex<C>> fc = PolyUtilRoot.<C> complexFromAny(f); 439 return complexAlgebraicNumbersComplex(fc, eps); 440 } 441 442 443 /** 444 * Filter real roots from complex roots. 445 * @param f univariate polynomial. 446 * @param c list of complex algebraic numbers. 447 * @param r list of real algebraic numbers. 448 * @return c minus the real roots from r 449 */ 450 public static <C extends GcdRingElem<C> & Rational> List<ComplexAlgebraicNumber<C>> filterOutRealRoots( 451 GenPolynomial<C> f, List<ComplexAlgebraicNumber<C>> c, List<RealAlgebraicNumber<C>> r) { 452 if (c.isEmpty()) { 453 return c; 454 } 455 if (r.isEmpty()) { 456 return c; 457 } 458 List<ComplexAlgebraicNumber<C>> cmr = new ArrayList<ComplexAlgebraicNumber<C>>(); 459 if (c.size() == r.size() /*&& r.size() == f.degree()*/ ) { 460 return cmr; 461 } 462 List<RealAlgebraicNumber<C>> rl = new LinkedList<RealAlgebraicNumber<C>>(r); 463 for (ComplexAlgebraicNumber<C> cn : c) { 464 RealAlgebraicNumber<C> rm = null; // ~boolean 465 for (RealAlgebraicNumber<C> rn : rl) { 466 if (isRealRoot(f, cn, rn)) { 467 //System.out.println("filterOutRealRoots, cn = " + cn + ", rn = " + rn); 468 rm = rn; 469 break; // remove from r 470 } 471 } 472 if (rm == null) { 473 cmr.add(cn); 474 } else { 475 rl.remove(rm); 476 } 477 } 478 return cmr; 479 } 480 481 482 /** 483 * Filter real roots from complex roots. 484 * @param f univariate polynomial. 485 * @param c list of complex decimal numbers. 486 * @param r list of real decimal numbers. 487 * @param eps desired precision. 488 * @return c minus the real roots from r 489 */ 490 public static <C extends GcdRingElem<C> & Rational> List<Complex<BigDecimal>> filterOutRealRoots( 491 GenPolynomial<C> f, List<Complex<BigDecimal>> c, List<BigDecimal> r, BigRational eps) { 492 if (c.isEmpty()) { 493 return c; 494 } 495 if (r.isEmpty()) { 496 return c; 497 } 498 List<Complex<BigDecimal>> cmr = new ArrayList<Complex<BigDecimal>>(); 499 if (c.size() == r.size() /*&& r.size() == f.degree()*/ ) { 500 return cmr; 501 } 502 List<BigDecimal> rl = new LinkedList<BigDecimal>(r); 503 for (Complex<BigDecimal> cn : c) { 504 BigDecimal rm = null; // ~boolean 505 for (BigDecimal rn : rl) { 506 if (isRealRoot(f, cn, rn, eps)) { 507 //System.out.println("filterOutRealRoots, cn = " + cn + ", rn = " + rn); 508 rm = rn; 509 break; // remove from r 510 } 511 } 512 if (rm == null) { 513 cmr.add(cn); 514 } else { 515 rl.remove(rm); 516 } 517 } 518 return cmr; 519 } 520 521 522 /** 523 * Roots as real and complex algebraic numbers. 524 * @param f univariate polynomial. 525 * @return container of real and complex algebraic numbers. 526 */ 527 public static <C extends GcdRingElem<C> & Rational> AlgebraicRoots<C> algebraicRoots(GenPolynomial<C> f) { 528 List<RealAlgebraicNumber<C>> rl = realAlgebraicNumbers(f); 529 List<ComplexAlgebraicNumber<C>> cl = complexAlgebraicNumbers(f); 530 GenPolynomial<Complex<C>> cf = null; 531 if (!cl.isEmpty()) { 532 cf = cl.get(0).ring.algebraic.modul; 533 } 534 cl = filterOutRealRoots(f, cl, rl); 535 AlgebraicRoots<C> ar = new AlgebraicRoots<C>(f, cf, rl, cl); 536 return ar; 537 } 538 539 540 /** 541 * Roots of unity of real and complex algebraic numbers. 542 * @param ar container of real and complex algebraic numbers. 543 * @return container of real and complex algebraic numbers which are roots 544 * of unity. 545 */ 546 public static <C extends GcdRingElem<C> & Rational> AlgebraicRoots<C> rootsOfUnity(AlgebraicRoots<C> ar) { 547 List<RealAlgebraicNumber<C>> rl = new ArrayList<RealAlgebraicNumber<C>>(); 548 for (RealAlgebraicNumber<C> r : ar.real) { 549 if (r.isRootOfUnity()) { 550 rl.add(r); 551 } 552 } 553 List<ComplexAlgebraicNumber<C>> cl = new ArrayList<ComplexAlgebraicNumber<C>>(); 554 for (ComplexAlgebraicNumber<C> c : ar.complex) { 555 if (c.isRootOfUnity()) { 556 cl.add(c); 557 } 558 } 559 AlgebraicRoots<C> ur = new AlgebraicRoots<C>(ar.p, ar.cp, rl, cl); 560 return ur; 561 } 562 563 564 /** 565 * Root refinement of real and complex algebraic numbers. 566 * @param a container of real and complex algebraic numbers. 567 * @param eps desired precision for root intervals and rectangles. 568 */ 569 public static <C extends GcdRingElem<C> & Rational> void rootRefine(AlgebraicRoots<C> a, 570 BigRational eps) { 571 for (RealAlgebraicNumber<C> r : a.real) { 572 r.ring.refineRoot(eps); 573 } 574 for (ComplexAlgebraicNumber<C> c : a.complex) { 575 c.ring.refineRoot(eps); 576 } 577 return; // a or void? 578 } 579 580 581 /** 582 * Roots as real and complex decimal numbers. 583 * @param f univariate polynomial. 584 * @param eps desired precision. 585 * @return container of real and complex decimal numbers. 586 */ 587 public static <C extends GcdRingElem<C> & Rational> DecimalRoots<C> decimalRoots(GenPolynomial<C> f, 588 BigRational eps) { 589 RealRootsAbstract<C> rengine = new RealRootsSturm<C>(); 590 List<BigDecimal> rl = rengine.approximateRoots(f, eps); 591 592 GenPolynomial<Complex<C>> fc = PolyUtilRoot.<C> complexFromAny(f); 593 ComplexRootsAbstract<C> cengine = new ComplexRootsSturm<C>(fc.ring.coFac); 594 List<Complex<BigDecimal>> cl = cengine.approximateRoots(fc, eps); 595 596 cl = filterOutRealRoots(f, cl, rl, eps); 597 DecimalRoots<C> ar = new DecimalRoots<C>(f, fc, rl, cl); 598 return ar; 599 } 600 601 602 /** 603 * Roots as real and complex decimal numbers. 604 * @param ar container for real and complex algebraic roots. 605 * @param eps desired precision. 606 * @return container of real and complex decimal numbers. 607 */ 608 public static <C extends GcdRingElem<C> & Rational> DecimalRoots<C> decimalRoots(AlgebraicRoots<C> ar, 609 BigRational eps) { 610 //no: rootRefine(ar, eps); 611 RealRootsAbstract<C> rengine = new RealRootsSturm<C>(); 612 List<BigDecimal> rl = new ArrayList<BigDecimal>(ar.real.size()); 613 for (RealAlgebraicNumber<C> r : ar.real) { 614 try { 615 BigDecimal d = rengine.approximateRoot(r.ring.root, ar.p, eps); 616 rl.add(d); 617 } catch (NoConvergenceException e) { 618 System.out.println("should not happen: " + e); 619 } 620 } 621 ComplexRootsAbstract<C> cengine = new ComplexRootsSturm<C>(ar.cp.ring.coFac); 622 List<Complex<BigDecimal>> cl = new ArrayList<Complex<BigDecimal>>(ar.complex.size()); 623 for (ComplexAlgebraicNumber<C> c : ar.complex) { 624 try { 625 Complex<BigDecimal> d = cengine.approximateRoot(c.ring.root, ar.cp, eps); 626 cl.add(d); 627 } catch (NoConvergenceException e) { 628 System.out.println("should not happen: " + e); 629 } 630 } 631 DecimalRoots<C> dr = new DecimalRoots<C>(ar.p, ar.cp, rl, cl); 632 return dr; 633 } 634 635}