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&lt;C&gt; 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&lt;C&gt; 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&lt;BigInteger&gt;
078     *            coefficients to be converted.
079     * @return polynomial with RealAlgebraicNumber&lt;C&gt; 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&lt;C&gt; coefficients to be
093     *            converted.
094     * @return polynomial with AlgebraicNumber&lt;C&gt; 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&lt;C&gt; coefficients to be
109     *            converted.
110     * @return polynomial with RealAlgebraicNumber&lt;C&gt; 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&lt;C&gt; 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&lt;C&gt; 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&lt;C&gt; 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&lt;C&gt; 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}