001    /*
002     * $Id: SquarefreeFiniteFieldCharP.java 3290 2010-08-26 09:18:48Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import java.util.SortedMap;
009    import java.util.TreeMap;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.arith.BigInteger;
014    import edu.jas.poly.ExpVector;
015    import edu.jas.poly.GenPolynomial;
016    import edu.jas.poly.GenPolynomialRing;
017    import edu.jas.poly.Monomial;
018    import edu.jas.structure.GcdRingElem;
019    import edu.jas.structure.Power;
020    import edu.jas.structure.RingFactory;
021    
022    
023    /**
024     * Squarefree decomposition for finite coefficient fields of characteristic p.
025     * @author Heinz Kredel
026     */
027    
028    public class SquarefreeFiniteFieldCharP<C extends GcdRingElem<C>> extends SquarefreeFieldCharP<C> {
029    
030    
031        private static final Logger logger = Logger.getLogger(SquarefreeFiniteFieldCharP.class);
032    
033    
034        private final boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Constructor.
039         */
040        public SquarefreeFiniteFieldCharP(RingFactory<C> fac) {
041            super(fac);
042            // isFinite() predicate now present
043            if ( !fac.isFinite() ) {
044                throw new IllegalArgumentException("fac must be finite"); 
045            }
046        }
047    
048    
049        /* --------- char-th roots --------------------- */
050    
051        /**
052         * Characteristics root of a coefficient. <b>Note:</b> not needed at the
053         * moment.
054         * @param p coefficient.
055         * @return [p -&gt; k] if exists k with e=k*charactristic(c) and c = p**e,
056         *         else null.
057         */
058        public SortedMap<C, Long> rootCharacteristic(C p) {
059            if (p == null) {
060                throw new IllegalArgumentException(this.getClass().getName() + " p == null");
061            }
062            // already checked in constructor:
063            //java.math.BigInteger c = p.factory().characteristic();
064            //if ( c.signum() == 0 ) {
065            //    return null;
066            //}
067            SortedMap<C, Long> root = new TreeMap<C, Long>();
068            if (p.isZERO()) {
069                return root;
070            }
071            // true for finite fields:
072            root.put(p, 1L);
073            return root;
074        }
075    
076    
077        /**
078         * Characteristics root of a coefficient.
079         * @param c coefficient.
080         * @return r with r**p == c, if such an r exists, else null.
081         */
082        public C coeffRootCharacteristic(C c) {
083            if (c == null || c.isZERO()) {
084                return c;
085            }
086            C r = c;
087            if (aCoFac == null && qCoFac == null) {
088                // case ModInteger: c**p == c
089                return r;
090            }
091            if (aCoFac != null) {
092                // case AlgebraicNumber<ModInteger>: r = c**(p**(d-1)), r**p == c
093                long d = aCoFac.totalExtensionDegree();
094                //System.out.println("d = " + d);
095                if (d <= 1) {
096                    return r;
097                }
098                BigInteger p = new BigInteger(aCoFac.characteristic());
099                BigInteger q = Power.<BigInteger> positivePower(p, d - 1);
100                //System.out.println("p**(d-1) = " + q);
101                r = Power.<C> positivePower(r, q.getVal());
102                //System.out.println("r**q = " + r);
103                return r;
104            }
105            if (qCoFac != null) {
106                throw new UnsupportedOperationException("case QuotientRing not yet implemented");
107            }
108            return r;
109        }
110    
111    
112        /**
113         * Characteristics root of a polynomial. <b>Note:</b> call only in
114         * recursion.
115         * @param P polynomial.
116         * @return [p -&gt; k] if exists k with e=k*charactristic(P) and P = p**e,
117         *         else null.
118         */
119        public SortedMap<GenPolynomial<C>, Long> rootCharacteristic(GenPolynomial<C> P) {
120            if (P == null) {
121                throw new IllegalArgumentException(this.getClass().getName() + " P == null");
122            }
123            java.math.BigInteger c = P.ring.characteristic();
124            if (c.signum() == 0) {
125                return null;
126            }
127            SortedMap<GenPolynomial<C>, Long> root = new TreeMap<GenPolynomial<C>, Long>();
128            if (P.isZERO()) {
129                return root;
130            }
131            if (P.isONE()) {
132                root.put(P, 1L);
133                return root;
134            }
135            SortedMap<GenPolynomial<C>, Long> sf = squarefreeFactors(P);
136            if (logger.isInfoEnabled()) {
137                logger.info("sf = " + sf);
138            }
139            // better: test if sf.size() == 1 // not ok
140            Long k = null;
141            for (GenPolynomial<C> p : sf.keySet()) {
142                if (p.isConstant()) {
143                    //System.out.println("p,const = " + p);
144                    continue;
145                }
146                Long e = sf.get(p);
147                java.math.BigInteger E = new java.math.BigInteger(e.toString());
148                java.math.BigInteger r = E.remainder(c);
149                if (!r.equals(java.math.BigInteger.ZERO)) {
150                    //System.out.println("r = " + r);
151                    return null;
152                }
153                if (k == null) {
154                    k = e;
155                } else if (k.compareTo(e) >= 0) {
156                    k = e;
157                }
158            }
159            // now c divides all exponents
160            Long cl = c.longValue();
161            GenPolynomial<C> rp = P.ring.getONE();
162            for (GenPolynomial<C> q : sf.keySet()) {
163                Long e = sf.get(q);
164                if (q.isConstant()) { // ensure p-th root
165                    C qc = q.leadingBaseCoefficient();
166                    //System.out.println("qc,const = " + qc + ", e = " + e);
167                    if (e > 1L) {
168                        qc = Power.<C> positivePower(qc, e);
169                        e = 1L;
170                    }
171                    C qr = coeffRootCharacteristic(qc);
172                    //System.out.println("qr,const = " + qr);
173                    q = P.ring.getONE().multiply(qr);
174                    root.put(q, 1L);
175                    continue;
176                }
177                if (e > k) {
178                    long ep = e / cl;
179                    q = Power.<GenPolynomial<C>> positivePower(q, ep);
180                }
181                rp = rp.multiply(q);
182            }
183            if (k != null) {
184                k = k / cl;
185                root.put(rp, k);
186            }
187            //System.out.println("sf,root = " + root);
188            return root;
189        }
190    
191    
192        /**
193         * GenPolynomial char-th root univariate polynomial. 
194         * Base coefficient type must be
195         * finite field, that is ModInteger or AlgebraicNumber&lt;ModInteger&gt;
196         * etc.
197         * @param P GenPolynomial.
198         * @return char-th_rootOf(P), or null if no char-th root.
199         */
200        @Override
201        public GenPolynomial<C> baseRootCharacteristic(GenPolynomial<C> P) {
202            if (P == null || P.isZERO()) {
203                return P;
204            }
205            GenPolynomialRing<C> pfac = P.ring;
206            if (pfac.nvar > 1) {
207                // basePthRoot not possible by return type
208                throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials");
209            }
210            RingFactory<C> rf = pfac.coFac;
211            if (rf.characteristic().signum() != 1) {
212                // basePthRoot not possible
213                throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf);
214            }
215            long mp = rf.characteristic().longValue();
216            GenPolynomial<C> d = pfac.getZERO().clone();
217            for (Monomial<C> m : P) {
218                ExpVector f = m.e;
219                long fl = f.getVal(0);
220                if (fl % mp != 0) {
221                    return null;
222                }
223                fl = fl / mp;
224                ExpVector e = ExpVector.create(1, 0, fl);
225                // for m.c exists a char-th root, since finite field
226                C r = coeffRootCharacteristic(m.c);
227                d.doPutToMap(e, r);
228            }
229            return d;
230        }
231    
232    
233        /**
234         * GenPolynomial char-th root univariate polynomial with polynomial coefficients.
235         * @param P recursive univariate GenPolynomial.
236         * @return char-th_rootOf(P), or null if P is no char-th root.
237         */
238        @Override
239        public GenPolynomial<GenPolynomial<C>> recursiveUnivariateRootCharacteristic(
240                GenPolynomial<GenPolynomial<C>> P) {
241            if (P == null || P.isZERO()) {
242                return P;
243            }
244            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
245            if (pfac.nvar > 1) {
246                // basePthRoot not possible by return type
247                throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials");
248            }
249            RingFactory<GenPolynomial<C>> rf = pfac.coFac;
250            if (rf.characteristic().signum() != 1) {
251                // basePthRoot not possible
252                throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf);
253            }
254            long mp = rf.characteristic().longValue();
255            GenPolynomial<GenPolynomial<C>> d = pfac.getZERO().clone();
256            for (Monomial<GenPolynomial<C>> m : P) {
257                ExpVector f = m.e;
258                long fl = f.getVal(0);
259                if (fl % mp != 0) {
260                    return null;
261                }
262                fl = fl / mp;
263                SortedMap<GenPolynomial<C>, Long> sm = rootCharacteristic(m.c);
264                if (sm == null) {
265                    return null;
266                }
267                if (logger.isInfoEnabled()) {
268                   logger.info("sm,rec = " + sm);
269                }
270                GenPolynomial<C> r = rf.getONE();
271                for (GenPolynomial<C> rp : sm.keySet()) {
272                    long gl = sm.get(rp);
273                    if (gl > 1) {
274                        rp = Power.<GenPolynomial<C>> positivePower(rp, gl);
275                    }
276                    r = r.multiply(rp);
277                }
278                ExpVector e = ExpVector.create(1, 0, fl);
279                //System.out.println("put-root r = " + r + ", e = " + e);
280                d.doPutToMap(e, r);
281            }
282            return d;
283        }
284    
285    }