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