001/* 002 * $Id: PolyUtilRoot.java 5579 2016-08-14 17:48:18Z kredel $ 003 */ 004 005package edu.jas.root; 006 007 008import java.util.ArrayList; 009import java.util.List; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.arith.Rational; 014import edu.jas.poly.AlgebraicNumber; 015import edu.jas.poly.AlgebraicNumberRing; 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.structure.RingFactory; 023import edu.jas.structure.UnaryFunctor; 024 025 026/** 027 * Polynomial utilities related to real and complex roots. 028 * @author Heinz Kredel 029 */ 030 031public class PolyUtilRoot { 032 033 034 private static final Logger logger = Logger.getLogger(PolyUtilRoot.class); 035 036 037 private static final boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with 042 * RealAlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 043 * @param pfac result polynomial factory. 044 * @param A polynomial with C coefficients to be converted. 045 * @return polynomial with RealAlgebraicNumber<C> coefficients. 046 */ 047 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<RealAlgebraicNumber<C>> convertToAlgebraicCoefficients( 048 GenPolynomialRing<RealAlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 049 RealAlgebraicRing<C> afac = (RealAlgebraicRing<C>) pfac.coFac; 050 if (debug) { 051 logger.info("afac = " + afac); 052 } 053 return PolyUtil.<C, RealAlgebraicNumber<C>> map(pfac, A, new CoeffToReAlg<C>(afac)); 054 } 055 056 057 /** 058 * Convert to recursive RealAlgebraicNumber coefficients. Represent as 059 * polynomial with recursive RealAlgebraicNumber<C> coefficients, C is e.g. 060 * ModInteger or BigRational. 061 * @param depth recursion depth of RealAlgebraicNumber coefficients. 062 * @param pfac result polynomial factory. 063 * @param A polynomial with C coefficients to be converted. 064 * @return polynomial with RealAlgebraicNumber<C> coefficients. 065 */ 066 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<RealAlgebraicNumber<C>> convertToRecAlgebraicCoefficients( 067 int depth, GenPolynomialRing<RealAlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 068 RealAlgebraicRing<C> afac = (RealAlgebraicRing<C>) pfac.coFac; 069 return PolyUtil.<C, RealAlgebraicNumber<C>> map(pfac, A, new CoeffToRecReAlg<C>(depth, afac)); 070 } 071 072 073 /** 074 * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with 075 * RealAlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 076 * @param pfac result polynomial factory. 077 * @param A recursive polynomial with GenPolynomial<BigInteger> 078 * coefficients to be converted. 079 * @return polynomial with RealAlgebraicNumber<C> coefficients. 080 */ 081 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<RealAlgebraicNumber<C>> convertRecursiveToAlgebraicCoefficients( 082 GenPolynomialRing<RealAlgebraicNumber<C>> pfac, GenPolynomial<GenPolynomial<C>> A) { 083 RealAlgebraicRing<C> afac = (RealAlgebraicRing<C>) pfac.coFac; 084 return PolyUtil.<GenPolynomial<C>, RealAlgebraicNumber<C>> map(pfac, A, new PolyToReAlg<C>(afac)); 085 } 086 087 088 /** 089 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 090 * AlgebraicNumber<C> coefficients. 091 * @param afac result polynomial factory. 092 * @param A polynomial with RealAlgebraicNumber<C> coefficients to be 093 * converted. 094 * @return polynomial with AlgebraicNumber<C> coefficients. 095 */ 096 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<AlgebraicNumber<C>> algebraicFromRealCoefficients( 097 GenPolynomialRing<AlgebraicNumber<C>> afac, GenPolynomial<RealAlgebraicNumber<C>> A) { 098 AlgebraicNumberRing<C> cfac = (AlgebraicNumberRing<C>) afac.coFac; 099 return PolyUtil.<RealAlgebraicNumber<C>, AlgebraicNumber<C>> map(afac, A, 100 new AlgFromRealCoeff<C>(cfac)); 101 } 102 103 104 /** 105 * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with 106 * RealAlgebraicNumber<C> coefficients. 107 * @param rfac result polynomial factory. 108 * @param A polynomial with AlgebraicNumber<C> coefficients to be 109 * converted. 110 * @return polynomial with RealAlgebraicNumber<C> coefficients. 111 */ 112 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<RealAlgebraicNumber<C>> realFromAlgebraicCoefficients( 113 GenPolynomialRing<RealAlgebraicNumber<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A) { 114 RealAlgebraicRing<C> cfac = (RealAlgebraicRing<C>) rfac.coFac; 115 return PolyUtil.<AlgebraicNumber<C>, RealAlgebraicNumber<C>> map(rfac, A, 116 new RealFromAlgCoeff<C>(cfac)); 117 } 118 119 120 /** 121 * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with 122 * RealAlgebraicNumber<C> coefficients, C is e.g. BigRational. 123 * @param pfac result polynomial factory. 124 * @param A polynomial with C coefficients to be converted. 125 * @return polynomial with RealAlgebraicNumber<C> coefficients. 126 */ 127 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<RealAlgebraicNumber<C>> convertToRealCoefficients( 128 GenPolynomialRing<RealAlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 129 RealAlgebraicRing<C> afac = (RealAlgebraicRing<C>) pfac.coFac; 130 return PolyUtil.<C, RealAlgebraicNumber<C>> map(pfac, A, new CoeffToReal<C>(afac)); 131 } 132 133 134 /** 135 * Convert to ComplexAlgebraicNumber coefficients. Represent as polynomial 136 * with ComplexAlgebraicNumber<C> coefficients, C is e.g. BigRational. 137 * @param pfac result polynomial factory. 138 * @param A polynomial with C coefficients to be converted. 139 * @return polynomial with ComplexAlgebraicNumber<C> coefficients. 140 */ 141 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<ComplexAlgebraicNumber<C>> convertToComplexCoefficients( 142 GenPolynomialRing<ComplexAlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 143 ComplexAlgebraicRing<C> afac = (ComplexAlgebraicRing<C>) pfac.coFac; 144 return PolyUtil.<C, ComplexAlgebraicNumber<C>> map(pfac, A, new CoeffToComplex<C>(afac)); 145 } 146 147 148 /** 149 * Convert to ComplexAlgebraicNumber coefficients. Represent as polynomial 150 * with ComplexAlgebraicNumber<C> coefficients, C is e.g. BigRational. 151 * @param pfac result polynomial factory. 152 * @param A polynomial with C coefficients to be converted. 153 * @return polynomial with ComplexAlgebraicNumber<C> coefficients. 154 */ 155 public static <C extends GcdRingElem<C> & Rational> GenPolynomial<ComplexAlgebraicNumber<C>> convertToComplexCoefficientsFromComplex( 156 GenPolynomialRing<ComplexAlgebraicNumber<C>> pfac, GenPolynomial<Complex<C>> A) { 157 ComplexAlgebraicRing<C> afac = (ComplexAlgebraicRing<C>) pfac.coFac; 158 return PolyUtil.<Complex<C>, ComplexAlgebraicNumber<C>> map(pfac, A, 159 new CoeffToComplexFromComplex<C>(afac)); 160 } 161 162 163 /** 164 * Convert to Complex coefficients. Represent as polynomial 165 * with Complex<C> coefficients. 166 * @param f univariate polynomial. 167 * @return f with complex coefficients 168 */ 169 public static <C extends GcdRingElem<C> & Rational> 170 GenPolynomial<Complex<C>> complexFromAny(GenPolynomial<C> f) { 171 if (f.ring.coFac instanceof ComplexRing) { 172 throw new IllegalArgumentException("f already has ComplexRing coefficients " + f.ring); 173 } 174 if (f.ring.coFac instanceof ComplexAlgebraicRing) { 175 throw new UnsupportedOperationException( 176 "unsupported ComplexAlgebraicRing coefficients " + f.ring); 177 } 178 ComplexRing<C> cr = new ComplexRing<C>(f.ring.coFac); 179 GenPolynomialRing<Complex<C>> fac = new GenPolynomialRing<Complex<C>>(cr, f.ring); 180 GenPolynomial<Complex<C>> fc = PolyUtil.<C> complexFromAny(fac, f); 181 return fc; 182 } 183} 184 185 186/** 187 * Polynomial to algebraic functor. 188 */ 189class PolyToReAlg<C extends GcdRingElem<C> & Rational> 190 implements UnaryFunctor<GenPolynomial<C>, RealAlgebraicNumber<C>> { 191 192 193 final protected RealAlgebraicRing<C> afac; 194 195 196 public PolyToReAlg(RealAlgebraicRing<C> fac) { 197 if (fac == null) { 198 throw new IllegalArgumentException("fac must not be null"); 199 } 200 afac = fac; 201 } 202 203 204 public RealAlgebraicNumber<C> eval(GenPolynomial<C> c) { 205 if (c == null) { 206 return afac.getZERO(); 207 } 208 return new RealAlgebraicNumber<C>(afac, c); 209 } 210} 211 212 213/** 214 * Coefficient to algebraic functor. 215 */ 216class CoeffToReAlg<C extends GcdRingElem<C> & Rational> implements UnaryFunctor<C, RealAlgebraicNumber<C>> { 217 218 219 final protected RealAlgebraicRing<C> afac; 220 221 222 final protected GenPolynomial<C> zero; 223 224 225 public CoeffToReAlg(RealAlgebraicRing<C> fac) { 226 if (fac == null) { 227 throw new IllegalArgumentException("fac must not be null"); 228 } 229 afac = fac; 230 GenPolynomialRing<C> pfac = afac.algebraic.ring; 231 zero = pfac.getZERO(); 232 } 233 234 235 public RealAlgebraicNumber<C> eval(C c) { 236 if (c == null) { 237 return afac.getZERO(); 238 } 239 return new RealAlgebraicNumber<C>(afac, zero.sum(c)); 240 } 241} 242 243 244/** 245 * Coefficient to recursive algebraic functor. 246 */ 247class CoeffToRecReAlg<C extends GcdRingElem<C> & Rational> 248 implements UnaryFunctor<C, RealAlgebraicNumber<C>> { 249 250 251 final protected List<RealAlgebraicRing<C>> lfac; 252 253 254 final int depth; 255 256 257 @SuppressWarnings({ "unchecked", "cast" }) 258 public CoeffToRecReAlg(int depth, RealAlgebraicRing<C> fac) { 259 if (fac == null) { 260 throw new IllegalArgumentException("fac must not be null"); 261 } 262 RealAlgebraicRing<C> afac = fac; 263 this.depth = depth; 264 lfac = new ArrayList<RealAlgebraicRing<C>>(this.depth); 265 lfac.add(fac); 266 for (int i = 1; i < this.depth; i++) { 267 RingFactory<C> rf = afac.algebraic.ring.coFac; 268 if (!(rf instanceof RealAlgebraicRing)) { 269 throw new IllegalArgumentException("fac depth to low"); 270 } 271 afac = (RealAlgebraicRing<C>) (Object) rf; 272 lfac.add(afac); 273 } 274 } 275 276 277 @SuppressWarnings("unchecked") 278 public RealAlgebraicNumber<C> eval(C c) { 279 if (c == null) { 280 return lfac.get(0).getZERO(); 281 } 282 C ac = c; 283 RealAlgebraicRing<C> af = lfac.get(lfac.size() - 1); 284 GenPolynomial<C> zero = af.algebraic.ring.getZERO(); 285 RealAlgebraicNumber<C> an = new RealAlgebraicNumber<C>(af, zero.sum(ac)); 286 for (int i = lfac.size() - 2; i >= 0; i--) { 287 af = lfac.get(i); 288 zero = af.algebraic.ring.getZERO(); 289 ac = (C) (Object) an; 290 an = new RealAlgebraicNumber<C>(af, zero.sum(ac)); 291 } 292 return an; 293 } 294} 295 296 297/** 298 * Coefficient to algebraic from real algebraic functor. 299 */ 300class AlgFromRealCoeff<C extends GcdRingElem<C> & Rational> 301 implements UnaryFunctor<RealAlgebraicNumber<C>, AlgebraicNumber<C>> { 302 303 304 final protected AlgebraicNumberRing<C> afac; 305 306 307 public AlgFromRealCoeff(AlgebraicNumberRing<C> fac) { 308 if (fac == null) { 309 throw new IllegalArgumentException("fac must not be null"); 310 } 311 afac = fac; 312 } 313 314 315 public AlgebraicNumber<C> eval(RealAlgebraicNumber<C> c) { 316 if (c == null) { 317 return afac.getZERO(); 318 } 319 return c.number; 320 } 321} 322 323 324/** 325 * Coefficient to real algebriac from algebraic functor. 326 */ 327class RealFromAlgCoeff<C extends GcdRingElem<C> & Rational> 328 implements UnaryFunctor<AlgebraicNumber<C>, RealAlgebraicNumber<C>> { 329 330 331 final protected RealAlgebraicRing<C> rfac; 332 333 334 public RealFromAlgCoeff(RealAlgebraicRing<C> fac) { 335 if (fac == null) { 336 throw new IllegalArgumentException("fac must not be null"); 337 } 338 rfac = fac; 339 } 340 341 342 public RealAlgebraicNumber<C> eval(AlgebraicNumber<C> c) { 343 if (c == null) { 344 return rfac.getZERO(); 345 } 346 return new RealAlgebraicNumber<C>(rfac, c); 347 } 348} 349 350 351/** 352 * Coefficient to real algebraic functor. 353 */ 354class CoeffToReal<C extends GcdRingElem<C> & Rational> implements UnaryFunctor<C, RealAlgebraicNumber<C>> { 355 356 357 final protected RealAlgebraicRing<C> rfac; 358 359 360 final protected AlgebraicNumber<C> zero; 361 362 363 public CoeffToReal(RealAlgebraicRing<C> fac) { 364 if (fac == null) { 365 throw new IllegalArgumentException("fac must not be null"); 366 } 367 rfac = fac; 368 AlgebraicNumberRing<C> afac = rfac.algebraic; 369 zero = afac.getZERO(); 370 } 371 372 373 public RealAlgebraicNumber<C> eval(C c) { 374 if (c == null) { 375 return rfac.getZERO(); 376 } 377 return new RealAlgebraicNumber<C>(rfac, zero.sum(c)); 378 } 379} 380 381 382/** 383 * Coefficient to complex algebraic functor. 384 */ 385class CoeffToComplex<C extends GcdRingElem<C> & Rational> 386 implements UnaryFunctor<C, ComplexAlgebraicNumber<C>> { 387 388 389 final protected ComplexAlgebraicRing<C> cfac; 390 391 392 final protected AlgebraicNumber<Complex<C>> zero; 393 394 395 final protected ComplexRing<C> cr; 396 397 398 public CoeffToComplex(ComplexAlgebraicRing<C> fac) { 399 if (fac == null) { 400 throw new IllegalArgumentException("fac must not be null"); 401 } 402 cfac = fac; 403 AlgebraicNumberRing<Complex<C>> afac = cfac.algebraic; 404 zero = afac.getZERO(); 405 cr = (ComplexRing<C>) afac.ring.coFac; 406 } 407 408 409 public ComplexAlgebraicNumber<C> eval(C c) { 410 if (c == null) { 411 return cfac.getZERO(); 412 } 413 return new ComplexAlgebraicNumber<C>(cfac, zero.sum(new Complex<C>(cr, c))); 414 } 415} 416 417 418/** 419 * Coefficient to complex algebraic from complex functor. 420 */ 421class CoeffToComplexFromComplex<C extends GcdRingElem<C> & Rational> 422 implements UnaryFunctor<Complex<C>, ComplexAlgebraicNumber<C>> { 423 424 425 final protected ComplexAlgebraicRing<C> cfac; 426 427 428 final protected AlgebraicNumber<Complex<C>> zero; 429 430 431 //final protected ComplexRing<C> cr; 432 433 434 public CoeffToComplexFromComplex(ComplexAlgebraicRing<C> fac) { 435 if (fac == null) { 436 throw new IllegalArgumentException("fac must not be null"); 437 } 438 cfac = fac; 439 AlgebraicNumberRing<Complex<C>> afac = cfac.algebraic; 440 zero = afac.getZERO(); 441 //cr = (ComplexRing<C>) afac.ring.coFac; 442 } 443 444 445 public ComplexAlgebraicNumber<C> eval(Complex<C> c) { 446 if (c == null) { 447 return cfac.getZERO(); 448 } 449 return new ComplexAlgebraicNumber<C>(cfac, zero.sum(c)); 450 } 451}