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