001/*
002 * $Id: PolyUfdUtil.java 5871 2018-07-20 15:58:45Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.ArrayList;
009import java.util.Collection;
010import java.util.List;
011import java.util.Map;
012
013import org.apache.logging.log4j.Logger;
014import org.apache.logging.log4j.LogManager; 
015
016import edu.jas.arith.BigInteger;
017import edu.jas.arith.BigRational;
018import edu.jas.poly.AlgebraicNumber;
019import edu.jas.poly.AlgebraicNumberRing;
020import edu.jas.poly.ExpVector;
021import edu.jas.poly.GenPolynomial;
022import edu.jas.poly.GenPolynomialRing;
023import edu.jas.poly.PolyUtil;
024import edu.jas.poly.TermOrderByName;
025import edu.jas.structure.GcdRingElem;
026import edu.jas.structure.RingElem;
027import edu.jas.structure.RingFactory;
028import edu.jas.structure.UnaryFunctor;
029import edu.jas.util.ListUtil;
030
031
032/**
033 * Polynomial ufd utilities. For example conversion between different representations
034 * and Kronecker substitution.
035 * @author Heinz Kredel
036 */
037
038public class PolyUfdUtil {
039
040
041    private static final Logger logger = LogManager.getLogger(PolyUfdUtil.class);
042
043
044    private static final boolean debug = logger.isDebugEnabled();
045
046
047    /**
048     * Integral polynomial from rational function coefficients. Represent as
049     * polynomial with integral polynomial coefficients by multiplication with
050     * the lcm of the numerators of the rational function coefficients.
051     * @param fac result polynomial factory.
052     * @param A polynomial with rational function coefficients to be converted.
053     * @return polynomial with integral polynomial coefficients.
054     */
055    public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> integralFromQuotientCoefficients(
056                    GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<Quotient<C>> A) {
057        GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy();
058        if (A == null || A.isZERO()) {
059            return B;
060        }
061        GenPolynomial<C> c = null;
062        GenPolynomial<C> d;
063        GenPolynomial<C> x;
064        GreatestCommonDivisor<C> ufd = new GreatestCommonDivisorSubres<C>();
065        int s = 0;
066        // lcm of denominators
067        for (Quotient<C> y : A.getMap().values()) {
068            x = y.den;
069            // c = lcm(c,x)
070            if (c == null) {
071                c = x;
072                s = x.signum();
073            } else {
074                d = ufd.gcd(c, x);
075                c = c.multiply(x.divide(d));
076            }
077        }
078        if (s < 0) {
079            c = c.negate();
080        }
081        for (Map.Entry<ExpVector, Quotient<C>> y : A.getMap().entrySet()) {
082            ExpVector e = y.getKey();
083            Quotient<C> a = y.getValue();
084            // p = n*(c/d)
085            GenPolynomial<C> b = c.divide(a.den);
086            GenPolynomial<C> p = a.num.multiply(b);
087            //B = B.sum( p, e ); // inefficient
088            B.doPutToMap(e, p);
089        }
090        return B;
091    }
092
093
094    /**
095     * Integral polynomial from rational function coefficients. Represent as
096     * polynomial with integral polynomial coefficients by multiplication with
097     * the lcm of the numerators of the rational function coefficients.
098     * @param fac result polynomial factory.
099     * @param L list of polynomial with rational function coefficients to be
100     *            converted.
101     * @return list of polynomials with integral polynomial coefficients.
102     */
103    public static <C extends GcdRingElem<C>> List<GenPolynomial<GenPolynomial<C>>> integralFromQuotientCoefficients(
104                    GenPolynomialRing<GenPolynomial<C>> fac, Collection<GenPolynomial<Quotient<C>>> L) {
105        if (L == null) {
106            return null;
107        }
108        List<GenPolynomial<GenPolynomial<C>>> list = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size());
109        for (GenPolynomial<Quotient<C>> p : L) {
110            list.add(integralFromQuotientCoefficients(fac, p));
111        }
112        return list;
113    }
114
115
116    /**
117     * Rational function from integral polynomial coefficients. Represent as
118     * polynomial with type Quotient<C> coefficients.
119     * @param fac result polynomial factory.
120     * @param A polynomial with integral polynomial coefficients to be
121     *            converted.
122     * @return polynomial with type Quotient<C> coefficients.
123     */
124    public static <C extends GcdRingElem<C>> GenPolynomial<Quotient<C>> quotientFromIntegralCoefficients(
125                    GenPolynomialRing<Quotient<C>> fac, GenPolynomial<GenPolynomial<C>> A) {
126        GenPolynomial<Quotient<C>> B = fac.getZERO().copy();
127        if (A == null || A.isZERO()) {
128            return B;
129        }
130        RingFactory<Quotient<C>> cfac = fac.coFac;
131        QuotientRing<C> qfac = (QuotientRing<C>) cfac;
132        for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.getMap().entrySet()) {
133            ExpVector e = y.getKey();
134            GenPolynomial<C> a = y.getValue();
135            Quotient<C> p = new Quotient<C>(qfac, a); // can not be zero
136            if (!p.isZERO()) {
137                //B = B.sum( p, e ); // inefficient
138                B.doPutToMap(e, p);
139            }
140        }
141        return B;
142    }
143
144
145    /**
146     * Rational function from integral polynomial coefficients. Represent as
147     * polynomial with type Quotient<C> coefficients.
148     * @param fac result polynomial factory.
149     * @param L list of polynomials with integral polynomial coefficients to be
150     *            converted.
151     * @return list of polynomials with type Quotient<C> coefficients.
152     */
153    public static <C extends GcdRingElem<C>> List<GenPolynomial<Quotient<C>>> quotientFromIntegralCoefficients(
154                    GenPolynomialRing<Quotient<C>> fac, Collection<GenPolynomial<GenPolynomial<C>>> L) {
155        if (L == null) {
156            return null;
157        }
158        List<GenPolynomial<Quotient<C>>> list = new ArrayList<GenPolynomial<Quotient<C>>>(L.size());
159        for (GenPolynomial<GenPolynomial<C>> p : L) {
160            list.add(quotientFromIntegralCoefficients(fac, p));
161        }
162        return list;
163    }
164
165
166    /**
167     * From BigInteger coefficients. Represent as polynomial with type
168     * GenPolynomial&lt;C&gt; coefficients, e.g. ModInteger or BigRational.
169     * @param fac result polynomial factory.
170     * @param A polynomial with GenPolynomial&lt;BigInteger&gt; coefficients to
171     *            be converted.
172     * @return polynomial with type GenPolynomial&lt;C&gt; coefficients.
173     */
174    public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> fromIntegerCoefficients(
175                    GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<GenPolynomial<BigInteger>> A) {
176        GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy();
177        if (A == null || A.isZERO()) {
178            return B;
179        }
180        RingFactory<GenPolynomial<C>> cfac = fac.coFac;
181        GenPolynomialRing<C> rfac = (GenPolynomialRing<C>) cfac;
182        for (Map.Entry<ExpVector, GenPolynomial<BigInteger>> y : A.getMap().entrySet()) {
183            ExpVector e = y.getKey();
184            GenPolynomial<BigInteger> a = y.getValue();
185            GenPolynomial<C> p = PolyUtil.<C> fromIntegerCoefficients(rfac, a);
186            if (!p.isZERO()) {
187                //B = B.sum( p, e ); // inefficient
188                B.doPutToMap(e, p);
189            }
190        }
191        return B;
192    }
193
194
195    /**
196     * From BigInteger coefficients. Represent as polynomial with type
197     * GenPolynomial&lt;C&gt; coefficients, e.g. ModInteger or BigRational.
198     * @param fac result polynomial factory.
199     * @param L polynomial list with GenPolynomial&lt;BigInteger&gt;
200     *            coefficients to be converted.
201     * @return polynomial list with polynomials with type GenPolynomial&lt;C&gt;
202     *         coefficients.
203     */
204    public static <C extends RingElem<C>> List<GenPolynomial<GenPolynomial<C>>> fromIntegerCoefficients(
205                    GenPolynomialRing<GenPolynomial<C>> fac, List<GenPolynomial<GenPolynomial<BigInteger>>> L) {
206        List<GenPolynomial<GenPolynomial<C>>> K = null;
207        if (L == null) {
208            return K;
209        }
210        K = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size());
211        if (L.size() == 0) {
212            return K;
213        }
214        for (GenPolynomial<GenPolynomial<BigInteger>> a : L) {
215            GenPolynomial<GenPolynomial<C>> b = fromIntegerCoefficients(fac, a);
216            K.add(b);
217        }
218        return K;
219    }
220
221    //------------------------------
222
223    /**
224     * BigInteger from BigRational coefficients. Represent as polynomial with type
225     * GenPolynomial&lt;BigInteger&gt; coefficients.
226     * @param fac result polynomial factory.
227     * @param A polynomial with GenPolynomial&lt;BigRational&gt; coefficients to
228     *            be converted.
229     * @return polynomial with type GenPolynomial&lt;BigInteger&gt; coefficients.
230     */
231    public static GenPolynomial<GenPolynomial<BigInteger>> integerFromRationalCoefficients(
232                    GenPolynomialRing<GenPolynomial<BigInteger>> fac, GenPolynomial<GenPolynomial<BigRational>> A) {
233        GenPolynomial<GenPolynomial<BigInteger>> B = fac.getZERO().copy();
234        if (A == null || A.isZERO()) {
235            return B;
236        }
237        java.math.BigInteger gcd = null;
238        java.math.BigInteger lcm = null;
239        int sLCM = 0;
240        int sGCD = 0;
241        // lcm of all denominators
242        for (GenPolynomial<BigRational> av : A.getMap().values()) {
243            for (BigRational y : av.getMap().values()) {
244                java.math.BigInteger numerator = y.numerator();
245                java.math.BigInteger denominator = y.denominator();
246                // lcm = lcm(lcm,x)
247                if (lcm == null) {
248                    lcm = denominator;
249                    sLCM = denominator.signum();
250                } else {
251                    java.math.BigInteger d = lcm.gcd(denominator);
252                    lcm = lcm.multiply(denominator.divide(d));
253                }
254                // gcd = gcd(gcd,x)
255                if (gcd == null) {
256                    gcd = numerator;
257                    sGCD = numerator.signum();
258                } else {
259                    gcd = gcd.gcd(numerator);
260                }
261            }
262            //System.out.println("gcd = " + gcd + ", lcm = " + lcm);
263        }
264        if (sLCM < 0) {
265            lcm = lcm.negate();
266        }
267        if (sGCD < 0) {
268            gcd = gcd.negate();
269        }
270        //System.out.println("gcd** = " + gcd + ", lcm = " + lcm);
271        RingFactory<GenPolynomial<BigInteger>> cfac = fac.coFac;
272        GenPolynomialRing<BigInteger> rfac = (GenPolynomialRing<BigInteger>) cfac;
273        for (Map.Entry<ExpVector, GenPolynomial<BigRational>> y : A.getMap().entrySet()) {
274            ExpVector e = y.getKey();
275            GenPolynomial<BigRational> a = y.getValue();
276            // common denominator over all coefficients
277            GenPolynomial<BigInteger> p = PolyUtil.integerFromRationalCoefficients(rfac, gcd, lcm, a);
278            if (!p.isZERO()) {
279                //B = B.sum( p, e ); // inefficient
280                B.doPutToMap(e, p);
281            }
282        }
283        return B;
284    }
285
286
287    /**
288     * BigInteger from BigRational coefficients. Represent as polynomial with type
289     * GenPolynomial&lt;BigInteger&gt; coefficients.
290     * @param fac result polynomial factory.
291     * @param L polynomial list with GenPolynomial&lt;BigRational&gt;
292     *            coefficients to be converted.
293     * @return polynomial list with polynomials with type GenPolynomial&lt;BigInteger&gt;
294     *         coefficients.
295     */
296    public static List<GenPolynomial<GenPolynomial<BigInteger>>> integerFromRationalCoefficients(
297                      GenPolynomialRing<GenPolynomial<BigInteger>> fac, List<GenPolynomial<GenPolynomial<BigRational>>> L) {
298        List<GenPolynomial<GenPolynomial<BigInteger>>> K = null;
299        if (L == null) {
300            return K;
301        }
302        K = new ArrayList<GenPolynomial<GenPolynomial<BigInteger>>>(L.size());
303        if (L.isEmpty()) {
304            return K;
305        }
306        for (GenPolynomial<GenPolynomial<BigRational>> a : L) {
307            GenPolynomial<GenPolynomial<BigInteger>> b = integerFromRationalCoefficients(fac, a);
308            K.add(b);
309        }
310        return K;
311    }
312
313
314    /**
315     * Introduce lower variable. Represent as polynomial with type
316     * GenPolynomial&lt;C&gt; coefficients.
317     * @param rfac result polynomial factory.
318     * @param A polynomial to be extended.
319     * @return polynomial with type GenPolynomial&lt;C&gt; coefficients.
320     */
321    public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> introduceLowerVariable(
322                    GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) {
323        if (A == null || rfac == null) {
324            return null;
325        }
326        GenPolynomial<GenPolynomial<C>> Pc = rfac.getONE().multiply(A);
327        if (Pc.isZERO()) {
328            return Pc;
329        }
330        Pc = PolyUtil.<C> switchVariables(Pc);
331        return Pc;
332    }
333
334
335    /**
336     * From AlgebraicNumber coefficients. Represent as polynomial with type
337     * GenPolynomial&lt;C&gt; coefficients, e.g. ModInteger or BigRational.
338     * @param rfac result polynomial factory.
339     * @param A polynomial with AlgebraicNumber coefficients to be converted.
340     * @param k for (y-k x) substitution.
341     * @return polynomial with type GenPolynomial&lt;C&gt; coefficients.
342     */
343    public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> substituteFromAlgebraicCoefficients(
344                    GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A, long k) {
345        if (A == null || rfac == null) {
346            return null;
347        }
348        if (A.isZERO()) {
349            return rfac.getZERO();
350        }
351        // setup x - k alpha
352        GenPolynomialRing<AlgebraicNumber<C>> apfac = A.ring;
353        GenPolynomial<AlgebraicNumber<C>> x = apfac.univariate(0);
354        AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) A.ring.coFac;
355        AlgebraicNumber<C> alpha = afac.getGenerator();
356        AlgebraicNumber<C> ka = afac.fromInteger(k);
357        GenPolynomial<AlgebraicNumber<C>> s = x.subtract(ka.multiply(alpha)); // x - k alpha
358        if (debug) {
359            logger.info("x - k alpha: " + s);
360        }
361        // substitute, convert and switch
362        GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<AlgebraicNumber<C>> substituteMain(A, s);
363        GenPolynomial<GenPolynomial<C>> Pc = PolyUtil.<C> fromAlgebraicCoefficients(rfac, B); // Q[alpha][x]
364        Pc = PolyUtil.<C> switchVariables(Pc); // Q[x][alpha]
365        return Pc;
366    }
367
368
369    /**
370     * Convert to AlgebraicNumber coefficients. Represent as polynomial with
371     * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational.
372     * @param pfac result polynomial factory.
373     * @param A polynomial with GenPolynomial&lt;BigInteger&gt; coefficients to
374     *            be converted.
375     * @param k for (y-k x) substitution.
376     * @return polynomial with AlgebraicNumber&lt;C&gt; coefficients.
377     */
378    public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> substituteConvertToAlgebraicCoefficients(
379                    GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A, long k) {
380        if (A == null || pfac == null) {
381            return null;
382        }
383        if (A.isZERO()) {
384            return pfac.getZERO();
385        }
386        // convert to Q(alpha)[x]
387        GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<C> convertToAlgebraicCoefficients(pfac, A);
388        // setup x .+. k alpha for back substitution
389        GenPolynomial<AlgebraicNumber<C>> x = pfac.univariate(0);
390        AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac;
391        AlgebraicNumber<C> alpha = afac.getGenerator();
392        AlgebraicNumber<C> ka = afac.fromInteger(k);
393        GenPolynomial<AlgebraicNumber<C>> s = x.sum(ka.multiply(alpha)); // x + k alpha
394        // substitute
395        GenPolynomial<AlgebraicNumber<C>> N = PolyUtil.<AlgebraicNumber<C>> substituteMain(B, s);
396        return N;
397    }
398
399
400    /**
401     * Norm of a polynomial with AlgebraicNumber coefficients.
402     * @param A polynomial from GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
403     * @param k for (y - k x) substitution.
404     * @return norm(A) = res_x(A(x,y),m(x)) in GenPolynomialRing&lt;C&gt;.
405     */
406    public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A, long k) {
407        if (A == null) {
408            return null;
409        }
410        GenPolynomialRing<AlgebraicNumber<C>> pfac = A.ring; // Q(alpha)[x]
411        if (pfac.nvar > 1) {
412            throw new IllegalArgumentException("only for univariate polynomials");
413        }
414        AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac;
415        GenPolynomial<C> agen = afac.modul;
416        GenPolynomialRing<C> cfac = afac.ring;
417        if (A.isZERO()) {
418            return cfac.getZERO();
419        }
420        AlgebraicNumber<C> ldcf = A.leadingBaseCoefficient();
421        if (!ldcf.isONE()) {
422            A = A.monic();
423        }
424        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pfac);
425
426        // transform minimal polynomial to bi-variate polynomial
427        GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, agen);
428        //System.out.println("Ac = " + Ac.toScript());
429
430        // transform to bi-variate polynomial, 
431        // switching varaible sequence from Q[alpha][x] to Q[X][alpha]
432        GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> substituteFromAlgebraicCoefficients(rfac, A, k);
433        Pc = PolyUtil.<C> monic(Pc);
434        //System.out.println("Pc = " + Pc.toScript());
435
436        GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>( /*cfac.coFac*/);
437        // = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getImplementation( cfac.coFac );
438
439        GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveUnivariateResultant(Pc, Ac);
440        //System.out.println("Rc = " + Rc.toScript());
441        GenPolynomial<C> res = Rc.leadingBaseCoefficient();
442        res = res.monic();
443        return res;
444    }
445
446
447    /**
448     * Norm of a polynomial with AlgebraicNumber coefficients.
449     * @param A polynomial from GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
450     * @return norm(A) = resultant_x( A(x,y), m(x) ) in K[y].
451     */
452    public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A) {
453        return norm(A, 0L);
454    }
455
456
457    /**
458     * Ensure that the field property is determined. Checks if modul is
459     * irreducible and modifies the algebraic number ring.
460     * @param afac algebraic number ring.
461     */
462    public static <C extends GcdRingElem<C>> void ensureFieldProperty(AlgebraicNumberRing<C> afac) {
463        if (afac.getField() != -1) {
464            return;
465        }
466        if (!afac.ring.coFac.isField()) {
467            afac.setField(false);
468            return;
469        }
470        Factorization<C> mf = FactorFactory.<C> getImplementation(afac.ring);
471        if (mf.isIrreducible(afac.modul)) {
472            afac.setField(true);
473        } else {
474            afac.setField(false);
475        }
476    }
477
478
479    /**
480     * Construct a random irreducible univariate polynomial of degree d.
481     * @param cfac coefficient ring.
482     * @param degree of random polynomial.
483     * @return irreducible univariate polynomial.
484     */
485    public static <C extends GcdRingElem<C>> 
486      GenPolynomial<C> randomIrreduciblePolynomial(RingFactory<C> cfac, int degree) {
487        if (!cfac.isField()) {
488            throw new IllegalArgumentException("coefficient ring must be a field " + cfac);
489        }
490        GenPolynomialRing<C> ring = new GenPolynomialRing<C>(cfac, 1, TermOrderByName.INVLEX);
491        Factorization<C> eng = FactorFactory.<C> getImplementation(ring);
492        GenPolynomial<C> mod = ring.getZERO();
493        int k = cfac.characteristic().bitLength(); // log
494        if (k < 3) {
495            k = 7;
496        }
497        int l = degree/2 + 2;
498        int d = degree + 1;
499        float q = 0.55f;
500        for (;;) {
501            mod = ring.random(k, l, d, q).monic();
502            if (mod.degree() != degree) {
503                mod  = mod.sum(ring.univariate(0, degree));
504            }
505            if (mod.trailingBaseCoefficient().isZERO()) {
506                mod  = mod.sum(ring.getONE());
507            }
508            //System.out.println("algebriacNumberField: mod = " + mod + ", k = " + k);
509            if (eng.isIrreducible(mod)) {
510                break;
511            }
512        }
513        return mod;
514    }
515
516
517    /**
518     * Construct an algebraic number field of degree d. Uses a random
519     * irreducible polynomial of degree d as modulus of the algebraic number ring.
520     * @param cfac coefficient ring.
521     * @param degree of random polynomial.
522     * @return algebraic number field.
523     */
524    public static <C extends GcdRingElem<C>> 
525      AlgebraicNumberRing<C> algebriacNumberField(RingFactory<C> cfac, int degree) {
526        GenPolynomial<C> mod = randomIrreduciblePolynomial(cfac, degree);
527        AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(mod, true);
528        return afac;
529    }
530
531
532    /**
533     * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a
534     * univariate polynomial.
535     * @param A polynomial to be converted.
536     * @return a univariate polynomial.
537     */
538    public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A) {
539        if (A == null) {
540            return A;
541        }
542        long d = A.degree() + 1L;
543        return substituteKronecker(A, d);
544    }
545
546
547    /**
548     * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a
549     * univariate polynomial.
550     * @param A polynomial to be converted.
551     * @return a univariate polynomial.
552     */
553    public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A, long d) {
554        if (A == null) {
555            return A;
556        }
557        RingFactory<C> cfac = A.ring.coFac;
558        GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1);
559        GenPolynomial<C> B = ufac.getZERO().copy();
560        if (A.isZERO()) {
561            return B;
562        }
563        for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) {
564            ExpVector e = y.getKey();
565            C a = y.getValue();
566            long f = 0L;
567            long h = 1L;
568            for (int i = 0; i < e.length(); i++) {
569                long j = e.getVal(i) * h;
570                f += j;
571                h *= d;
572            }
573            ExpVector g = ExpVector.create(1, 0, f);
574            B.doPutToMap(g, a);
575        }
576        return B;
577    }
578
579
580    /**
581     * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct 
582     * univariate polynomials.
583     * @param A list of polynomials to be converted.
584     * @return a list of univariate polynomials.
585     */
586    public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> substituteKronecker(
587                    List<GenPolynomial<C>> A, int d) {
588        if (A == null || A.get(0) == null) {
589            return null;
590        }
591        return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new SubstKronecker<C>(d));
592    }
593
594
595    /**
596     * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a
597     * multivariate polynomial.
598     * @param A polynomial to be converted.
599     * @param fac result polynomial factory.
600     * @return a multivariate polynomial.
601     */
602    public static <C extends GcdRingElem<C>> GenPolynomial<C> backSubstituteKronecker(
603                    GenPolynomialRing<C> fac, GenPolynomial<C> A, long d) {
604        if (A == null) {
605            return A;
606        }
607        if (fac == null) {
608            throw new IllegalArgumentException("null factory not allowed ");
609        }
610        int n = fac.nvar;
611        GenPolynomial<C> B = fac.getZERO().copy();
612        if (A.isZERO()) {
613            return B;
614        }
615        for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) {
616            ExpVector e = y.getKey();
617            C a = y.getValue();
618            long f = e.getVal(0);
619            ExpVector g = ExpVector.create(n);
620            for (int i = 0; i < n; i++) {
621                long j = f % d;
622                f /= d;
623                g = g.subst(i, j);
624            }
625            B.doPutToMap(g, a);
626        }
627        return B;
628    }
629
630
631    /**
632     * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct 
633     * multivariate polynomials.
634     * @param A list of polynomials to be converted.
635     * @param fac result polynomial factory.
636     * @return a list of multivariate polynomials.
637     */
638    public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> backSubstituteKronecker(
639                    GenPolynomialRing<C> fac, List<GenPolynomial<C>> A, long d) {
640        return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new BackSubstKronecker<C>(fac, d));
641    }
642
643}
644
645
646/**
647 * Kronecker substitutuion functor.
648 */
649class SubstKronecker<C extends GcdRingElem<C>> implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> {
650
651
652    final long d;
653
654
655    public SubstKronecker(long d) {
656        this.d = d;
657    }
658
659
660    public GenPolynomial<C> eval(GenPolynomial<C> c) {
661        if (c == null) {
662            return null;
663        }
664        return PolyUfdUtil.<C> substituteKronecker(c, d);
665    }
666}
667
668
669/**
670 * Kronecker back substitutuion functor.
671 */
672class BackSubstKronecker<C extends GcdRingElem<C>> implements
673                UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> {
674
675
676    final long d;
677
678
679    final GenPolynomialRing<C> fac;
680
681
682    public BackSubstKronecker(GenPolynomialRing<C> fac, long d) {
683        this.d = d;
684        this.fac = fac;
685    }
686
687
688    public GenPolynomial<C> eval(GenPolynomial<C> c) {
689        if (c == null) {
690            return null;
691        }
692        return PolyUfdUtil.<C> backSubstituteKronecker(fac, c, d);
693    }
694}