001/*
002 * $Id: PolyUtilRoot.java 4961 2014-10-17 18:59:39Z 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 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, new AlgFromRealCoeff<C>(
100                        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, new RealFromAlgCoeff<C>(
116                        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
165/**
166 * Polynomial to algebraic functor.
167 */
168class PolyToReAlg<C extends GcdRingElem<C> & Rational> implements
169                UnaryFunctor<GenPolynomial<C>, RealAlgebraicNumber<C>> {
170
171
172    final protected RealAlgebraicRing<C> afac;
173
174
175    public PolyToReAlg(RealAlgebraicRing<C> fac) {
176        if (fac == null) {
177            throw new IllegalArgumentException("fac must not be null");
178        }
179        afac = fac;
180    }
181
182
183    public RealAlgebraicNumber<C> eval(GenPolynomial<C> c) {
184        if (c == null) {
185            return afac.getZERO();
186        }
187        return new RealAlgebraicNumber<C>(afac, c);
188    }
189}
190
191
192/**
193 * Coefficient to algebraic functor.
194 */
195class CoeffToReAlg<C extends GcdRingElem<C> & Rational> implements UnaryFunctor<C, RealAlgebraicNumber<C>> {
196
197
198    final protected RealAlgebraicRing<C> afac;
199
200
201    final protected GenPolynomial<C> zero;
202
203
204    public CoeffToReAlg(RealAlgebraicRing<C> fac) {
205        if (fac == null) {
206            throw new IllegalArgumentException("fac must not be null");
207        }
208        afac = fac;
209        GenPolynomialRing<C> pfac = afac.algebraic.ring;
210        zero = pfac.getZERO();
211    }
212
213
214    public RealAlgebraicNumber<C> eval(C c) {
215        if (c == null) {
216            return afac.getZERO();
217        }
218        return new RealAlgebraicNumber<C>(afac, zero.sum(c));
219    }
220}
221
222
223/**
224 * Coefficient to recursive algebraic functor.
225 */
226class CoeffToRecReAlg<C extends GcdRingElem<C> & Rational> implements UnaryFunctor<C, RealAlgebraicNumber<C>> {
227
228
229    final protected List<RealAlgebraicRing<C>> lfac;
230
231
232    final int depth;
233
234
235    @SuppressWarnings("cast")
236    public CoeffToRecReAlg(int depth, RealAlgebraicRing<C> fac) {
237        if (fac == null) {
238            throw new IllegalArgumentException("fac must not be null");
239        }
240        RealAlgebraicRing<C> afac = fac;
241        this.depth = depth;
242        lfac = new ArrayList<RealAlgebraicRing<C>>(this.depth);
243        lfac.add(fac);
244        for (int i = 1; i < this.depth; i++) {
245            RingFactory<C> rf = afac.algebraic.ring.coFac;
246            if (!(rf instanceof RealAlgebraicRing)) {
247                throw new IllegalArgumentException("fac depth to low");
248            }
249            afac = (RealAlgebraicRing<C>) (Object) rf;
250            lfac.add(afac);
251        }
252    }
253
254
255    @SuppressWarnings("cast")
256    public RealAlgebraicNumber<C> eval(C c) {
257        if (c == null) {
258            return lfac.get(0).getZERO();
259        }
260        C ac = c;
261        RealAlgebraicRing<C> af = lfac.get(lfac.size() - 1);
262        GenPolynomial<C> zero = af.algebraic.ring.getZERO();
263        RealAlgebraicNumber<C> an = new RealAlgebraicNumber<C>(af, zero.sum(ac));
264        for (int i = lfac.size() - 2; i >= 0; i--) {
265            af = lfac.get(i);
266            zero = af.algebraic.ring.getZERO();
267            ac = (C) (Object) an;
268            an = new RealAlgebraicNumber<C>(af, zero.sum(ac));
269        }
270        return an;
271    }
272}
273
274
275/**
276 * Coefficient to algebraic from real algebraic functor.
277 */
278class AlgFromRealCoeff<C extends GcdRingElem<C> & Rational> implements
279                UnaryFunctor<RealAlgebraicNumber<C>, AlgebraicNumber<C>> {
280
281
282    final protected AlgebraicNumberRing<C> afac;
283
284
285    public AlgFromRealCoeff(AlgebraicNumberRing<C> fac) {
286        if (fac == null) {
287            throw new IllegalArgumentException("fac must not be null");
288        }
289        afac = fac;
290    }
291
292
293    public AlgebraicNumber<C> eval(RealAlgebraicNumber<C> c) {
294        if (c == null) {
295            return afac.getZERO();
296        }
297        return c.number;
298    }
299}
300
301
302/**
303 * Coefficient to real algebriac from algebraic functor.
304 */
305class RealFromAlgCoeff<C extends GcdRingElem<C> & Rational> implements
306                UnaryFunctor<AlgebraicNumber<C>, RealAlgebraicNumber<C>> {
307
308
309    final protected RealAlgebraicRing<C> rfac;
310
311
312    public RealFromAlgCoeff(RealAlgebraicRing<C> fac) {
313        if (fac == null) {
314            throw new IllegalArgumentException("fac must not be null");
315        }
316        rfac = fac;
317    }
318
319
320    public RealAlgebraicNumber<C> eval(AlgebraicNumber<C> c) {
321        if (c == null) {
322            return rfac.getZERO();
323        }
324        return new RealAlgebraicNumber<C>(rfac, c);
325    }
326}
327
328
329/**
330 * Coefficient to real algebraic functor.
331 */
332class CoeffToReal<C extends GcdRingElem<C> & Rational> implements UnaryFunctor<C, RealAlgebraicNumber<C>> {
333
334
335    final protected RealAlgebraicRing<C> rfac;
336
337
338    final protected AlgebraicNumber<C> zero;
339
340
341    public CoeffToReal(RealAlgebraicRing<C> fac) {
342        if (fac == null) {
343            throw new IllegalArgumentException("fac must not be null");
344        }
345        rfac = fac;
346        AlgebraicNumberRing<C> afac = rfac.algebraic;
347        zero = afac.getZERO();
348    }
349
350
351    public RealAlgebraicNumber<C> eval(C c) {
352        if (c == null) {
353            return rfac.getZERO();
354        }
355        return new RealAlgebraicNumber<C>(rfac, zero.sum(c));
356    }
357}
358
359
360/**
361 * Coefficient to complex algebraic functor.
362 */
363class CoeffToComplex<C extends GcdRingElem<C> & Rational> implements
364                UnaryFunctor<C, ComplexAlgebraicNumber<C>> {
365
366
367    final protected ComplexAlgebraicRing<C> cfac;
368
369
370    final protected AlgebraicNumber<Complex<C>> zero;
371
372
373    final protected ComplexRing<C> cr;
374
375
376    public CoeffToComplex(ComplexAlgebraicRing<C> fac) {
377        if (fac == null) {
378            throw new IllegalArgumentException("fac must not be null");
379        }
380        cfac = fac;
381        AlgebraicNumberRing<Complex<C>> afac = cfac.algebraic;
382        zero = afac.getZERO();
383        cr = (ComplexRing<C>) afac.ring.coFac;
384    }
385
386
387    public ComplexAlgebraicNumber<C> eval(C c) {
388        if (c == null) {
389            return cfac.getZERO();
390        }
391        return new ComplexAlgebraicNumber<C>(cfac, zero.sum(new Complex<C>(cr, c)));
392    }
393}
394
395
396/**
397 * Coefficient to complex algebraic from complex functor.
398 */
399class CoeffToComplexFromComplex<C extends GcdRingElem<C> & Rational> implements
400                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        }
427        return new ComplexAlgebraicNumber<C>(cfac, zero.sum(c));
428    }
429}