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