001/*
002 * $Id: SquarefreeFieldCharP.java 5871 2018-07-20 15:58:45Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.Map;
009import java.util.SortedMap;
010import java.util.TreeMap;
011
012import org.apache.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.poly.AlgebraicNumber;
016import edu.jas.poly.AlgebraicNumberRing;
017import edu.jas.poly.ExpVector;
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;
023
024
025/**
026 * Squarefree decomposition for coefficient fields of characteristic p.
027 * @author Heinz Kredel
028 */
029
030public abstract class SquarefreeFieldCharP<C extends GcdRingElem<C>> extends SquarefreeAbstract<C> {
031
032
033    private static final Logger logger = LogManager.getLogger(SquarefreeFieldCharP.class);
034
035
036    private static final boolean debug = logger.isDebugEnabled();
037
038
039    /*
040     * Squarefree engine for characteristic p base coefficients.
041     */
042    //protected final SquarefreeAbstract<C> rengine;
043
044
045    /**
046     * Factory for finite field of characteristic p coefficients.
047     */
048    protected final RingFactory<C> coFac;
049
050
051    /**
052     * Factory for a algebraic extension of a finite field of characteristic p
053     * coefficients. If <code>coFac</code> is an algebraic extension, then
054     * <code>aCoFac</code> is equal to <code>coFac</code>, else
055     * <code>aCoFac</code> is <code>null</code>.
056     */
057    protected final AlgebraicNumberRing<C> aCoFac;
058
059
060    /**
061     * Factory for a transcendental extension of a finite field of
062     * characteristic p coefficients. If <code>coFac</code> is an transcendental
063     * extension, then <code>qCoFac</code> is equal to <code>coFac</code>, else
064     * <code>qCoFac</code> is <code>null</code>.
065     */
066    protected final QuotientRing<C> qCoFac;
067
068
069    /**
070     * Constructor.
071     */
072    @SuppressWarnings("unchecked")
073    public SquarefreeFieldCharP(RingFactory<C> fac) {
074        super(GCDFactory.<C> getProxy(fac));
075        if (!fac.isField()) {
076            //throw new IllegalArgumentException("fac must be a field: "  + fac.toScript());
077            logger.warn("fac should be a field: " + fac.toScript());
078        }
079        if (fac.characteristic().signum() == 0) {
080            throw new IllegalArgumentException("characterisic(fac) must be non-zero");
081        }
082        coFac = fac;
083        Object oFac = coFac;
084        if (oFac instanceof AlgebraicNumberRing) {
085            aCoFac = (AlgebraicNumberRing<C>) oFac; // <C> is not correct
086            //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(aCoFac.ring);
087            qCoFac = null;
088        } else {
089            aCoFac = null;
090            if (oFac instanceof QuotientRing) {
091                qCoFac = (QuotientRing<C>) oFac; // <C> is not correct
092                //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(qCoFac.ring);
093            } else {
094                qCoFac = null;
095            }
096        }
097    }
098
099
100    /**
101     * Get the String representation.
102     * @see java.lang.Object#toString()
103     */
104    @Override
105    public String toString() {
106        return getClass().getName() + " with " + engine + " over " + coFac;
107    }
108
109
110    /**
111     * GenPolynomial polynomial greatest squarefree divisor.
112     * @param P GenPolynomial.
113     * @return squarefree(pp(P)).
114     */
115    @Override
116    public GenPolynomial<C> baseSquarefreePart(GenPolynomial<C> P) {
117        if (P == null || P.isZERO()) {
118            return P;
119        }
120        GenPolynomialRing<C> pfac = P.ring;
121        if (pfac.nvar > 1) {
122            throw new IllegalArgumentException(
123                            this.getClass().getName() + " only for univariate polynomials");
124        }
125        GenPolynomial<C> s = pfac.getONE();
126        SortedMap<GenPolynomial<C>, Long> factors = baseSquarefreeFactors(P);
127        if (logger.isWarnEnabled()) {
128           logger.warn("sqfPart, better use sqfFactors, factors = " + factors);
129        }
130        for (GenPolynomial<C> sp : factors.keySet()) {
131            s = s.multiply(sp);
132        }
133        s = s.monic();
134        return s;
135    }
136
137
138    /**
139     * GenPolynomial polynomial squarefree factorization.
140     * @param A GenPolynomial.
141     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
142     *         p_i^{e_i} and p_i squarefree.
143     */
144    @Override
145    public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) {
146        SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
147        if (A == null || A.isZERO()) {
148            return sfactors;
149        }
150        GenPolynomialRing<C> pfac = A.ring;
151        if (A.isConstant()) {
152            C coeff = A.leadingBaseCoefficient();
153            //System.out.println("coeff = " + coeff + " @ " + coeff.factory());
154            SortedMap<C, Long> rfactors = squarefreeFactors(coeff);
155            //System.out.println("rfactors,const = " + rfactors);
156            if (rfactors != null && rfactors.size() > 0) {
157                for (Map.Entry<C, Long> me : rfactors.entrySet()) {
158                    C c = me.getKey();
159                    if (!c.isONE()) {
160                        GenPolynomial<C> cr = pfac.getONE().multiply(c);
161                        Long rk = me.getValue(); // rfactors.get(c);
162                        sfactors.put(cr, rk);
163                    }
164                }
165            } else {
166                sfactors.put(A, 1L);
167            }
168            return sfactors;
169        }
170        if (pfac.nvar > 1) {
171            throw new IllegalArgumentException(
172                            this.getClass().getName() + " only for univariate polynomials");
173        }
174        C ldbcf = A.leadingBaseCoefficient();
175        if (!ldbcf.isONE()) {
176            A = A.divide(ldbcf);
177            SortedMap<C, Long> rfactors = squarefreeFactors(ldbcf);
178            //System.out.println("rfactors,ldbcf = " + rfactors);
179            if (rfactors != null && rfactors.size() > 0) {
180                for (Map.Entry<C, Long> me : rfactors.entrySet()) {
181                    C c = me.getKey();
182                    if (!c.isONE()) {
183                        GenPolynomial<C> cr = pfac.getONE().multiply(c);
184                        Long rk = me.getValue(); //rfactors.get(c);
185                        sfactors.put(cr, rk);
186                    }
187                }
188            } else {
189                GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf);
190                //System.out.println("gcda sqf f1 = " + f1);
191                sfactors.put(f1, 1L);
192            }
193            ldbcf = pfac.coFac.getONE();
194        }
195        GenPolynomial<C> T0 = A;
196        long e = 1L;
197        GenPolynomial<C> Tp;
198        GenPolynomial<C> T = null;
199        GenPolynomial<C> V = null;
200        long k = 0L;
201        long mp = 0L;
202        boolean init = true;
203        while (true) {
204            //System.out.println("T0 = " + T0);
205            if (init) {
206                if (T0.isConstant() || T0.isZERO()) {
207                    break;
208                }
209                Tp = PolyUtil.<C> baseDeriviative(T0);
210                T = engine.baseGcd(T0, Tp);
211                T = T.monic();
212                V = PolyUtil.<C> basePseudoDivide(T0, T);
213                //System.out.println("iT0 = " + T0);
214                //System.out.println("iTp = " + Tp);
215                //System.out.println("iT  = " + T);
216                //System.out.println("iV  = " + V);
217                //System.out.println("const(iV)  = " + V.isConstant());
218                k = 0L;
219                mp = 0L;
220                init = false;
221            }
222            if (V.isConstant()) {
223                mp = pfac.characteristic().longValue(); // assert != 0
224                //T0 = PolyUtil.<C> baseModRoot(T,mp);
225                T0 = baseRootCharacteristic(T);
226                logger.info("char root: T0 = " + T0 + ", T = " + T);
227                if (T0 == null) {
228                    //break;
229                    T0 = pfac.getZERO();
230                }
231                e = e * mp;
232                init = true;
233                continue;
234            }
235            k++;
236            if (mp != 0L && k % mp == 0L) {
237                T = PolyUtil.<C> basePseudoDivide(T, V);
238                System.out.println("k = " + k);
239                //System.out.println("T = " + T);
240                k++;
241            }
242            GenPolynomial<C> W = engine.baseGcd(T, V);
243            W = W.monic();
244            GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W);
245            //System.out.println("W = " + W);
246            //System.out.println("z = " + z);
247            V = W;
248            T = PolyUtil.<C> basePseudoDivide(T, V);
249            //System.out.println("V = " + V);
250            //System.out.println("T = " + T);
251            if (z.degree(0) > 0) {
252                if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) {
253                    z = z.monic();
254                    logger.info("z,monic = " + z);
255                }
256                sfactors.put(z, (e * k));
257            }
258        }
259        logger.info("exit char root: T0 = " + T0 + ", T = " + T);
260        return sfactors;
261    }
262
263
264    /**
265     * GenPolynomial recursive univariate polynomial greatest squarefree
266     * divisor.
267     * @param P recursive univariate GenPolynomial.
268     * @return squarefree(pp(P)).
269     */
270    @Override
271    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart(
272                    GenPolynomial<GenPolynomial<C>> P) {
273        if (P == null || P.isZERO()) {
274            return P;
275        }
276        GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
277        if (pfac.nvar > 1) {
278            throw new IllegalArgumentException(
279                            this.getClass().getName() + " only for univariate polynomials");
280        }
281        GenPolynomial<GenPolynomial<C>> s = pfac.getONE();
282        SortedMap<GenPolynomial<GenPolynomial<C>>, Long> factors = recursiveUnivariateSquarefreeFactors(P);
283        if (logger.isWarnEnabled()) {
284            logger.warn("sqfPart, better use sqfFactors, factors = " + factors);
285        }
286        for (GenPolynomial<GenPolynomial<C>> sp : factors.keySet()) {
287            s = s.multiply(sp);
288        }
289        return PolyUtil.<C> monic(s);
290    }
291
292
293    /**
294     * GenPolynomial recursive univariate polynomial squarefree factorization.
295     * @param P recursive univariate GenPolynomial.
296     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
297     *         p_i^{e_i} and p_i squarefree.
298     */
299    @Override
300    public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors(
301                    GenPolynomial<GenPolynomial<C>> P) {
302        SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>();
303        if (P == null || P.isZERO()) {
304            return sfactors;
305        }
306        GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
307        if (pfac.nvar > 1) {
308            // recursiveContent not possible by return type
309            throw new IllegalArgumentException(
310                            this.getClass().getName() + " only for univariate polynomials");
311        }
312        // if base coefficient ring is a field, make monic
313        GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
314        C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
315        if (!ldbcf.isONE()) {
316            GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf);
317            GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc);
318            sfactors.put(pl, 1L);
319            C li = ldbcf.inverse();
320            //System.out.println("li = " + li);
321            P = P.multiply(cfac.getONE().multiply(li));
322            //System.out.println("P,monic = " + P);
323            ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
324            if (debug) {
325                logger.debug("new ldbcf: " + ldbcf);
326            }
327        }
328        // factors of content
329        GenPolynomial<C> Pc = engine.recursiveContent(P);
330        if (logger.isInfoEnabled()) {
331            logger.info("Pc = " + Pc);
332        }
333        Pc = Pc.monic();
334        if (!Pc.isONE()) {
335            P = PolyUtil.<C> coefficientPseudoDivide(P, Pc);
336        }
337        SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc);
338        if (logger.isInfoEnabled()) {
339            logger.info("rsf = " + rsf);
340        }
341        // add factors of content
342        for (Map.Entry<GenPolynomial<C>, Long> me : rsf.entrySet()) {
343            GenPolynomial<C> c = me.getKey();
344            if (!c.isONE()) {
345                GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c);
346                Long rk = me.getValue(); //rsf.get(c);
347                sfactors.put(cr, rk);
348            }
349        }
350        // divide by trailing term
351        ExpVector et = P.trailingExpVector();
352        if (!et.isZERO()) {
353            GenPolynomial<GenPolynomial<C>> tr = pfac.valueOf(et);
354            if (logger.isInfoEnabled()) {
355                logger.info("trailing term = " + tr);
356            }
357            P = PolyUtil.<C> recursivePseudoDivide(P, tr);
358            long ep = et.getVal(0); // univariate
359            et = et.subst(0, 1);
360            tr = pfac.valueOf(et);
361            sfactors.put(tr, ep);
362        }
363
364        // factors of recursive polynomial
365        GenPolynomial<GenPolynomial<C>> T0 = P;
366        long e = 1L;
367        GenPolynomial<GenPolynomial<C>> Tp;
368        GenPolynomial<GenPolynomial<C>> T = null;
369        GenPolynomial<GenPolynomial<C>> V = null;
370        long k = 0L;
371        long mp = 0L;
372        boolean init = true;
373        while (true) {
374            if (init) {
375                if (T0.isConstant() || T0.isZERO()) {
376                    break;
377                }
378                Tp = PolyUtil.<C> recursiveDeriviative(T0);
379                T = engine.recursiveUnivariateGcd(T0, Tp);
380                T = PolyUtil.<C> monic(T);
381                V = PolyUtil.<C> recursivePseudoDivide(T0, T);
382                //System.out.println("iT0 = " + T0);
383                //System.out.println("iTp = " + Tp);
384                //System.out.println("iT = " + T);
385                //System.out.println("iV = " + V);
386                k = 0L;
387                mp = 0L;
388                init = false;
389            }
390            if (V.isConstant()) {
391                mp = pfac.characteristic().longValue(); // assert != 0
392                //T0 = PolyUtil.<C> recursiveModRoot(T,mp);
393                T0 = recursiveUnivariateRootCharacteristic(T);
394                logger.info("char root: T0r = " + T0 + ", Tr = " + T);
395                if (T0 == null) {
396                    //break;
397                    T0 = pfac.getZERO();
398                }
399                e = e * mp;
400                init = true;
401                //continue;
402            }
403            k++;
404            if (mp != 0L && k % mp == 0L) {
405                T = PolyUtil.<C> recursivePseudoDivide(T, V);
406                System.out.println("k = " + k);
407                //System.out.println("T = " + T);
408                k++;
409            }
410            GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V);
411            W = PolyUtil.<C> monic(W);
412            GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W);
413            //System.out.println("W = " + W);
414            //System.out.println("z = " + z);
415            V = W;
416            T = PolyUtil.<C> recursivePseudoDivide(T, V);
417            //System.out.println("V = " + V);
418            //System.out.println("T = " + T);
419            //was: if ( z.degree(0) > 0 ) {
420            if (!z.isONE() && !z.isZERO()) {
421                z = PolyUtil.<C> monic(z);
422                logger.info("z,put = " + z);
423                sfactors.put(z, (e * k));
424            }
425        }
426        logger.info("exit char root: T0 = " + T0 + ", T = " + T);
427        if (sfactors.size() == 0) {
428            sfactors.put(pfac.getONE(), 1L);
429        }
430        return sfactors;
431    }
432
433
434    /**
435     * GenPolynomial greatest squarefree divisor.
436     * @param P GenPolynomial.
437     * @return squarefree(pp(P)).
438     */
439    @Override
440    public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) {
441        if (P == null) {
442            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
443        }
444        if (P.isZERO()) {
445            return P;
446        }
447        GenPolynomialRing<C> pfac = P.ring;
448        if (pfac.nvar <= 1) {
449            return baseSquarefreePart(P);
450        }
451        GenPolynomial<C> s = pfac.getONE();
452        SortedMap<GenPolynomial<C>, Long> factors = squarefreeFactors(P);
453        if (logger.isWarnEnabled()) {
454            logger.warn("sqfPart, better use sqfFactors, factors = " + factors);
455        }
456        for (GenPolynomial<C> sp : factors.keySet()) {
457            if (sp.isConstant()) {
458                continue;
459            }
460            s = s.multiply(sp);
461        }
462        return s.monic();
463    }
464
465
466    /**
467     * GenPolynomial squarefree factorization.
468     * @param P GenPolynomial.
469     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
470     *         p_i^{e_i} and p_i squarefree.
471     */
472    @Override
473    public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) {
474        if (P == null) {
475            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
476        }
477        GenPolynomialRing<C> pfac = P.ring;
478        if (pfac.nvar <= 1) {
479            return baseSquarefreeFactors(P);
480        }
481        SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
482        if (P.isZERO()) {
483            return sfactors;
484        }
485        if (P.isONE()) {
486            sfactors.put(P, 1L);
487            return sfactors;
488        }
489        GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
490        GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
491        SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr);
492        for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) {
493            Long i = m.getValue();
494            GenPolynomial<GenPolynomial<C>> Dr = m.getKey();
495            GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
496            sfactors.put(D, i);
497        }
498        return sfactors;
499    }
500
501
502    /**
503     * Coefficient squarefree factorization.
504     * @param coeff coefficient.
505     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
506     *         p_i^{e_i} and p_i squarefree.
507     */
508    @SuppressWarnings("unchecked")
509    @Override
510    public SortedMap<C, Long> squarefreeFactors(C coeff) {
511        if (coeff == null) {
512            return null;
513        }
514        SortedMap<C, Long> factors = new TreeMap<C, Long>();
515        RingFactory<C> cfac = (RingFactory<C>) coeff.factory();
516        if (aCoFac != null) {
517            AlgebraicNumber<C> an = (AlgebraicNumber<C>) (Object) coeff;
518            if (cfac.isFinite()) {
519                SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory
520                                .getImplementation(cfac);
521                SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ??
522                logger.info("rfactors,finite = " + rfactors);
523                factors.putAll(rfactors);
524                //return factors;
525            } else {
526                SquarefreeInfiniteAlgebraicFieldCharP<C> reng = (SquarefreeInfiniteAlgebraicFieldCharP) SquarefreeFactory
527                                .getImplementation(cfac);
528                SortedMap<AlgebraicNumber<C>, Long> rfactors = reng.squarefreeFactors(an);
529                logger.info("rfactors,infinite,algeb = " + rfactors);
530                for (Map.Entry<AlgebraicNumber<C>, Long> me : rfactors.entrySet()) {
531                    AlgebraicNumber<C> c = me.getKey();
532                    if (!c.isONE()) {
533                        C cr = (C) (Object) c;
534                        Long rk = me.getValue();
535                        factors.put(cr, rk);
536                    }
537                }
538            }
539        } else if (qCoFac != null) {
540            Quotient<C> q = (Quotient<C>) (Object) coeff;
541            SquarefreeInfiniteFieldCharP<C> reng = (SquarefreeInfiniteFieldCharP) SquarefreeFactory
542                            .getImplementation(cfac);
543            SortedMap<Quotient<C>, Long> rfactors = reng.squarefreeFactors(q);
544            logger.info("rfactors,infinite = " + rfactors);
545            for (Map.Entry<Quotient<C>, Long> me : rfactors.entrySet()) {
546                Quotient<C> c = me.getKey();
547                if (!c.isONE()) {
548                    C cr = (C) (Object) c;
549                    Long rk = me.getValue();
550                    factors.put(cr, rk);
551                }
552            }
553        } else if (cfac.isFinite()) {
554            SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory
555                            .getImplementation(cfac);
556            SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ??
557            logger.info("rfactors,finite = " + rfactors);
558            factors.putAll(rfactors);
559            //return factors;
560        } else {
561            logger.warn("case " + cfac + " not implemented");
562        }
563        return factors;
564    }
565
566
567    /* --------- char-th roots --------------------- */
568
569
570    /**
571     * GenPolynomial char-th root univariate polynomial.
572     * @param P GenPolynomial.
573     * @return char-th_rootOf(P), or null if no char-th root.
574     */
575    public abstract GenPolynomial<C> baseRootCharacteristic(GenPolynomial<C> P);
576
577
578    /**
579     * GenPolynomial char-th root univariate polynomial with polynomial
580     * coefficients.
581     * @param P recursive univariate GenPolynomial.
582     * @return char-th_rootOf(P), or null if P is no char-th root.
583     */
584    public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateRootCharacteristic(
585                    GenPolynomial<GenPolynomial<C>> P);
586
587
588    /**
589     * Polynomial is char-th root.
590     * @param P polynomial.
591     * @param F = [p_1 -&gt; e_1, ..., p_k -&gt; e_k].
592     * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false.
593     */
594    public boolean isCharRoot(GenPolynomial<C> P, SortedMap<GenPolynomial<C>, Long> F) {
595        if (P == null || F == null) {
596            throw new IllegalArgumentException("P and F may not be null");
597        }
598        if (P.isZERO() && F.size() == 0) {
599            return true;
600        }
601        GenPolynomial<C> t = P.ring.getONE();
602        long p = P.ring.characteristic().longValue();
603        for (Map.Entry<GenPolynomial<C>, Long> me : F.entrySet()) {
604            GenPolynomial<C> f = me.getKey();
605            Long E = me.getValue();
606            long e = E.longValue();
607            GenPolynomial<C> g = f.power(e);
608            if (!f.isConstant()) {
609                g = g.power(p);
610            }
611            t = t.multiply(g);
612        }
613        boolean f = P.equals(t) || P.equals(t.negate());
614        if (!f) {
615            System.out.println("\nfactorization(map): " + f);
616            System.out.println("P = " + P);
617            System.out.println("t = " + t);
618            P = P.monic();
619            t = t.monic();
620            f = P.equals(t) || P.equals(t.negate());
621            if (f) {
622                return f;
623            }
624            System.out.println("\nfactorization(map): " + f);
625            System.out.println("P = " + P);
626            System.out.println("t = " + t);
627        }
628        return f;
629    }
630
631
632    /**
633     * Recursive polynomial is char-th root.
634     * @param P recursive polynomial.
635     * @param F = [p_1 -&gt; e_1, ..., p_k -&gt; e_k].
636     * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false.
637     */
638    public boolean isRecursiveCharRoot(GenPolynomial<GenPolynomial<C>> P,
639                    SortedMap<GenPolynomial<GenPolynomial<C>>, Long> F) {
640        if (P == null || F == null) {
641            throw new IllegalArgumentException("P and F may not be null");
642        }
643        if (P.isZERO() && F.size() == 0) {
644            return true;
645        }
646        GenPolynomial<GenPolynomial<C>> t = P.ring.getONE();
647        long p = P.ring.characteristic().longValue();
648        for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> me : F.entrySet()) {
649            GenPolynomial<GenPolynomial<C>> f = me.getKey();
650            Long E = me.getValue();
651            long e = E.longValue();
652            GenPolynomial<GenPolynomial<C>> g = f.power(e);
653            if (!f.isConstant()) {
654                g = g.power(p);
655            }
656            t = t.multiply(g);
657        }
658        boolean f = P.equals(t) || P.equals(t.negate());
659        if (!f) {
660            System.out.println("\nfactorization(map): " + f);
661            System.out.println("P = " + P);
662            System.out.println("t = " + t);
663            P = P.monic();
664            t = t.monic();
665            f = P.equals(t) || P.equals(t.negate());
666            if (f) {
667                return f;
668            }
669            System.out.println("\nfactorization(map): " + f);
670            System.out.println("P = " + P);
671            System.out.println("t = " + t);
672        }
673        return f;
674    }
675
676
677    /**
678     * Recursive polynomial is char-th root.
679     * @param P recursive polynomial.
680     * @param r = recursive polynomial.
681     * @return true if P = r**p, else false.
682     */
683    public boolean isRecursiveCharRoot(GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> r) {
684        if (P == null || r == null) {
685            throw new IllegalArgumentException("P and r may not be null");
686        }
687        if (P.isZERO() && r.isZERO()) {
688            return true;
689        }
690        long p = P.ring.characteristic().longValue();
691        GenPolynomial<GenPolynomial<C>> t = r.power(p);
692
693        boolean f = P.equals(t) || P.equals(t.negate());
694        if (!f) {
695            System.out.println("\nisCharRoot: " + f);
696            System.out.println("P = " + P);
697            System.out.println("t = " + t);
698            P = P.monic();
699            t = t.monic();
700            f = P.equals(t) || P.equals(t.negate());
701            if (f) {
702                return f;
703            }
704            System.out.println("\nisCharRoot: " + f);
705            System.out.println("P = " + P);
706            System.out.println("t = " + t);
707        }
708        return f;
709    }
710
711}