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