001    /*
002     * $Id: SquarefreeFieldChar0.java 3752 2011-08-27 19:23:49Z 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.GenPolynomial;
017    import edu.jas.poly.GenPolynomialRing;
018    import edu.jas.poly.PolyUtil;
019    import edu.jas.structure.GcdRingElem;
020    import edu.jas.structure.RingFactory;
021    
022    
023    /**
024     * Squarefree decomposition for coefficient fields of characteristic 0.
025     * @author Heinz Kredel
026     */
027    
028    public class SquarefreeFieldChar0<C extends GcdRingElem<C>> extends SquarefreeAbstract<C> {
029    
030    
031        private static final Logger logger = Logger.getLogger(SquarefreeFieldChar0.class);
032    
033    
034        private final boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Factory for field of characteristic 0 coefficients.
039         */
040        protected final RingFactory<C> coFac;
041    
042    
043        /**
044         * Constructor.
045         */
046        public SquarefreeFieldChar0(RingFactory<C> fac) {
047            super( GCDFactory.<C> getProxy(fac) );
048            if (!fac.isField()) {
049                throw new IllegalArgumentException("fac must be a field");
050            }
051            if (fac.characteristic().signum() != 0) {
052                throw new IllegalArgumentException("characterisic(fac) must be zero");
053            }
054            coFac = fac;
055        }
056    
057    
058        /**
059         * Get the String representation.
060         * @see java.lang.Object#toString()
061         */
062        @Override
063        public String toString() {
064            return getClass().getName() + " with " + engine + " over " + coFac;
065        }
066    
067    
068        /**
069         * GenPolynomial polynomial greatest squarefree divisor.
070         * @param P GenPolynomial.
071         * @return squarefree(pp(P)).
072         */
073        @Override
074        public GenPolynomial<C> baseSquarefreePart(GenPolynomial<C> P) {
075            if (P == null || P.isZERO()) {
076                return P;
077            }
078            GenPolynomialRing<C> pfac = P.ring;
079            if (pfac.nvar > 1) {
080                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
081            }
082            GenPolynomial<C> pp = P.monic();
083            if (pp.isConstant()) {
084                return pp;
085            }
086            GenPolynomial<C> d = PolyUtil.<C> baseDeriviative(pp);
087            d = d.monic();
088            //System.out.println("d = " + d);
089            GenPolynomial<C> g = engine.baseGcd(pp, d);
090            g = g.monic();
091            GenPolynomial<C> q = PolyUtil.<C> basePseudoDivide(pp, g);
092            q = q.monic();
093            return q;
094        }
095    
096    
097        /**
098         * GenPolynomial test if is squarefree.
099         * @param P GenPolynomial.
100         * @return true if P is squarefree, else false.
101         */
102        public boolean isBaseSquarefree(GenPolynomial<C> P) {
103            if (P == null || P.isZERO()) {
104                return true;
105            }
106            GenPolynomialRing<C> pfac = P.ring;
107            if (pfac.nvar > 1) {
108                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
109            }
110            GenPolynomial<C> pp = P.monic();
111            if (pp.isConstant()) {
112                return true;
113            }
114            GenPolynomial<C> d = PolyUtil.<C> baseDeriviative(pp);
115            d = d.monic();
116            //System.out.println("d = " + d);
117            GenPolynomial<C> g = engine.baseGcd(pp, d);
118            g = g.monic();
119            return g.isONE();
120        }
121    
122    
123        /**
124         * GenPolynomial polynomial squarefree factorization.
125         * @param A GenPolynomial.
126         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
127         *         and p_i squarefree.
128         */
129        @Override
130        public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) {
131            SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
132            if (A == null || A.isZERO()) {
133                return sfactors;
134            }
135            if (A.isConstant()) {
136                sfactors.put(A, 1L);
137                return sfactors;
138            }
139            GenPolynomialRing<C> pfac = A.ring;
140            if (pfac.nvar > 1) {
141                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
142            }
143            C ldbcf = A.leadingBaseCoefficient();
144            if (!ldbcf.isONE()) {
145                A = A.divide(ldbcf);
146                GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf);
147                //System.out.println("gcda sqf f1 = " + f1);
148                sfactors.put(f1, 1L);
149                ldbcf = pfac.coFac.getONE();
150            }
151            GenPolynomial<C> T0 = A;
152            GenPolynomial<C> Tp;
153            GenPolynomial<C> T = null;
154            GenPolynomial<C> V = null;
155            long k = 0L;
156            boolean init = true;
157            while (true) {
158                if (init) {
159                    if (T0.isConstant() || T0.isZERO()) {
160                        break;
161                    }
162                    Tp = PolyUtil.<C> baseDeriviative(T0);
163                    T = engine.baseGcd(T0, Tp);
164                    T = T.monic();
165                    V = PolyUtil.<C> basePseudoDivide(T0, T);
166                    //System.out.println("iT0 = " + T0);
167                    //System.out.println("iTp = " + Tp);
168                    //System.out.println("iT  = " + T);
169                    //System.out.println("iV  = " + V);
170                    k = 0L;
171                    init = false;
172                }
173                if (V.isConstant()) {
174                    break;
175                }
176                k++;
177                GenPolynomial<C> W = engine.baseGcd(T, V);
178                W = W.monic();
179                GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W);
180                //System.out.println("W = " + W);
181                //System.out.println("z = " + z);
182                V = W;
183                T = PolyUtil.<C> basePseudoDivide(T, V);
184                //System.out.println("V = " + V);
185                //System.out.println("T = " + T);
186                if (z.degree(0) > 0) {
187                    if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) {
188                        z = z.monic();
189                        logger.info("z,monic = " + z);
190                    }
191                    sfactors.put(z, k);
192                }
193            }
194            //      look, a stupid error:
195            //         if ( pfac.coFac.isField() && !ldbcf.isONE() ) {
196            //             GenPolynomial<C> f1 = sfactors.firstKey();
197            //             long e1 = sfactors.remove(f1);
198            //             System.out.println("gcda sqf c = " + c);
199            //             f1 = f1.multiply(c);
200            //             //System.out.println("gcda sqf f1e = " + f1);
201            //             sfactors.put(f1,e1);
202            //         }
203            return sfactors;
204        }
205    
206    
207        /**
208         * GenPolynomial recursive univariate polynomial greatest squarefree
209         * divisor.
210         * @param P recursive univariate GenPolynomial.
211         * @return squarefree(pp(P)).
212         */
213        @Override
214        public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart(GenPolynomial<GenPolynomial<C>> P) {
215            if (P == null || P.isZERO()) {
216                return P;
217            }
218            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
219            if (pfac.nvar > 1) {
220                throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials");
221            }
222            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
223            // squarefree content
224            GenPolynomial<GenPolynomial<C>> pp = P;
225            GenPolynomial<C> Pc = engine.recursiveContent(P);
226            Pc = Pc.monic();
227            if (!Pc.isONE()) {
228                pp = PolyUtil.<C> coefficientPseudoDivide(pp, Pc);
229                //System.out.println("pp,sqp = " + pp);
230                GenPolynomial<C> Pr = squarefreePart(Pc);
231                Pr = Pr.monic();
232                //System.out.println("Pr,sqp = " + Pr);
233            }
234            if (pp.leadingExpVector().getVal(0) < 1) {
235                //System.out.println("pp = " + pp);
236                //System.out.println("Pc = " + Pc);
237                return pp.multiply(Pc);
238            }
239            GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp);
240            //System.out.println("d = " + d);
241            GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d);
242            //System.out.println("g,rec = " + g);
243            g = PolyUtil.<C> monic(g);
244            GenPolynomial<GenPolynomial<C>> q = PolyUtil.<C> recursivePseudoDivide(pp, g);
245            q = PolyUtil.<C> monic(q);
246            return q.multiply(Pc);
247        }
248    
249    
250        /**
251         * GenPolynomial test if is squarefree.
252         * @param P GenPolynomial.
253         * @return true if P is squarefree, else false.
254         */
255        public boolean isRecursiveUnivariateSquarefree(GenPolynomial<GenPolynomial<C>> P) {
256            if (P == null || P.isZERO()) {
257                return true;
258            }
259            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
260            if (pfac.nvar > 1) {
261                throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials");
262            }
263            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
264            // squarefree content
265            GenPolynomial<GenPolynomial<C>> pp = P;
266            GenPolynomial<C> Pc = engine.recursiveContent(P);
267            if ( logger.isInfoEnabled() ) {
268                logger.info("recursiveContent = " + Pc);
269            }
270            if ( ! isSquarefree(Pc) ) {
271                return false;
272            }
273            Pc = Pc.monic();
274            if (!Pc.isONE()) {
275                pp = PolyUtil.<C> coefficientPseudoDivide(pp, Pc);
276                //System.out.println("pp,sqp = " + pp);
277            }
278            if (pp.leadingExpVector().getVal(0) <= 1) {
279                //System.out.println("pp = " + pp);
280                //System.out.println("Pc = " + Pc);
281                return true;
282            }
283            GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp);
284            //System.out.println("d = " + d);
285            GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d);
286            if ( logger.isInfoEnabled() ) {
287                logger.info("gcd = " + g);
288            }
289            //System.out.println("g,rec = " + g);
290            g = PolyUtil.<C> monic(g);
291            return g.isONE();
292        }
293    
294    
295        /**
296         * GenPolynomial recursive univariate polynomial squarefree factorization.
297         * @param P recursive univariate GenPolynomial.
298         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
299         *         and p_i squarefree.
300         */
301        @Override
302        public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors(
303                GenPolynomial<GenPolynomial<C>> P) {
304            SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>();
305            if (P == null || P.isZERO()) {
306                return sfactors;
307            }
308            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
309            if (pfac.nvar > 1) {
310                // recursiveContent not possible by return type
311                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
312            }
313            // if base coefficient ring is a field, make monic
314            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
315            C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
316            if (!ldbcf.isONE()) {
317                GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf);
318                GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc);
319                sfactors.put(pl, 1L);
320                C li = ldbcf.inverse();
321                //System.out.println("li = " + li);
322                P = P.multiply(cfac.getONE().multiply(li));
323                //System.out.println("P,monic = " + P);
324                ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
325            }
326            // factors of content
327            GenPolynomial<C> Pc = engine.recursiveContent(P);
328            if ( logger.isInfoEnabled() ) {
329                logger.info("recursiveContent = " + Pc);
330            }
331            Pc = Pc.monic();
332            if (!Pc.isONE()) {
333                P = PolyUtil.<C> coefficientPseudoDivide(P, Pc);
334            }
335            SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc);
336            if ( logger.isInfoEnabled() ) {
337                logger.info("squarefreeFactors = " + rsf);
338            }
339            // add factors of content
340            for (GenPolynomial<C> c : rsf.keySet()) {
341                if (!c.isONE()) {
342                    GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c);
343                    Long rk = rsf.get(c);
344                    sfactors.put(cr, rk);
345                }
346            }
347    
348            // factors of recursive polynomial
349            GenPolynomial<GenPolynomial<C>> T0 = P;
350            GenPolynomial<GenPolynomial<C>> Tp;
351            GenPolynomial<GenPolynomial<C>> T = null;
352            GenPolynomial<GenPolynomial<C>> V = null;
353            long k = 0L;
354            boolean init = true;
355            while (true) {
356                if (init) {
357                    if (T0.isConstant() || T0.isZERO()) {
358                        break;
359                    }
360                    Tp = PolyUtil.<C> recursiveDeriviative(T0);
361                    T = engine.recursiveUnivariateGcd(T0, Tp);
362                    T = PolyUtil.<C> monic(T);
363                    V = PolyUtil.<C> recursivePseudoDivide(T0, T);
364                    //System.out.println("iT0 = " + T0);
365                    //System.out.println("iTp = " + Tp);
366                    //System.out.println("iT = " + T);
367                    //System.out.println("iV = " + V);
368                    k = 0L;
369                    init = false;
370                }
371                if (V.isConstant()) {
372                    break;
373                }
374                k++;
375                GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V);
376                W = PolyUtil.<C> monic(W);
377                GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W);
378                //System.out.println("W = " + W);
379                //System.out.println("z = " + z);
380                V = W;
381                T = PolyUtil.<C> recursivePseudoDivide(T, V);
382                //System.out.println("V = " + V);
383                //System.out.println("T = " + T);
384                //was: if ( z.degree(0) > 0 ) {
385                if (!z.isONE() && !z.isZERO()) {
386                    if (ldbcf.isONE()) {
387                        z = PolyUtil.<C> monic(z);
388                        logger.info("z,monic = " + z);
389                    }
390                    sfactors.put(z, k);
391                }
392            }
393            return sfactors;
394        }
395    
396    
397        /**
398         * GenPolynomial greatest squarefree divisor.
399         * @param P GenPolynomial.
400         * @return squarefree(pp(P)).
401         */
402        @Override
403        public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) {
404            if (P == null) {
405                throw new IllegalArgumentException(this.getClass().getName() + " P != null");
406            }
407            if (P.isZERO()) {
408                return P;
409            }
410            GenPolynomialRing<C> pfac = P.ring;
411            if (pfac.nvar <= 1) {
412                return baseSquarefreePart(P);
413            }
414            GenPolynomialRing<C> cfac = pfac.contract(1);
415            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
416    
417            GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
418            GenPolynomial<C> Pc = engine.recursiveContent(Pr);
419            Pr = PolyUtil.<C> coefficientPseudoDivide(Pr, Pc);
420            GenPolynomial<C> Ps = squarefreePart(Pc);
421            if ( logger.isInfoEnabled() ) {
422                logger.info("content = " + Pc + ", squarefreePart = " + Ps);
423            }
424            GenPolynomial<GenPolynomial<C>> PP = recursiveUnivariateSquarefreePart(Pr);
425            GenPolynomial<GenPolynomial<C>> PS = PP.multiply(Ps);
426            GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PS);
427            if ( logger.isInfoEnabled() ) {
428                logger.info("univRec = " + Pr + ", squarefreePart = " + PP);
429            }
430            return D;
431        }
432    
433    
434        /**
435         * GenPolynomial test if is squarefree.
436         * @param P GenPolynomial.
437         * @return true if P is squarefree, else false.
438         */
439        @Override
440        public boolean isSquarefree(GenPolynomial<C> P) {
441            if (P == null) {
442                throw new IllegalArgumentException(this.getClass().getName() + " P != null");
443            }
444            if (P.isZERO()) {
445                return true;
446            }
447            GenPolynomialRing<C> pfac = P.ring;
448            if (pfac.nvar <= 1) {
449                return isBaseSquarefree(P);
450            }
451            GenPolynomialRing<C> cfac = pfac.contract(1);
452            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
453            GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
454            return isRecursiveUnivariateSquarefree(Pr);
455        }
456    
457    
458        /**
459         * GenPolynomial squarefree factorization.
460         * @param P GenPolynomial.
461         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
462         *         and p_i squarefree.
463         */
464        @Override
465        public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) {
466            if (P == null) {
467                throw new IllegalArgumentException(this.getClass().getName() + " P != null");
468            }
469            GenPolynomialRing<C> pfac = P.ring;
470            if (pfac.nvar <= 1) {
471                return baseSquarefreeFactors(P);
472            }
473            SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
474            if (P.isZERO()) {
475                return sfactors;
476            }
477            GenPolynomialRing<C> cfac = pfac.contract(1);
478            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
479    
480            GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
481            SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr);
482    
483            for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) {
484                Long i = m.getValue();
485                GenPolynomial<GenPolynomial<C>> Dr = m.getKey();
486                GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
487                sfactors.put(D, i);
488            }
489            if ( logger.isInfoEnabled() ) {
490                logger.info("squarefreeFactors(" + P + ") = " + sfactors);
491            }
492            return sfactors;
493        }
494    
495    
496        /**
497         * Coefficients squarefree factorization.
498         * @param P coefficient.
499         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
500         *         and p_i squarefree.
501         */
502        public SortedMap<C, Long> squarefreeFactors(C P) {
503            throw new UnsupportedOperationException("method not implemented");
504        }
505    
506    }