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