001    /*
002     * $Id: SquarefreeRingChar0.java 3297 2010-08-26 19:09:03Z 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 rings of characteristic 0.
025     * @author Heinz Kredel
026     */
027    
028    public class SquarefreeRingChar0<C extends GcdRingElem<C>> extends SquarefreeAbstract<C> /*implements Squarefree<C>*/{
029    
030    
031        private static final Logger logger = Logger.getLogger(SquarefreeRingChar0.class);
032    
033    
034        private final boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Factory for ring of characteristic 0 coefficients.
039         */
040        protected final RingFactory<C> coFac;
041    
042    
043        /**
044         * Constructor.
045         */
046        public SquarefreeRingChar0(RingFactory<C> fac) {
047            super( GCDFactory.<C> getProxy(fac) );
048            if (fac.isField()) {
049                throw new IllegalArgumentException("fac is a field: use SquarefreeFieldChar0");
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 = engine.basePrimitivePart(P);
083            if (pp.isConstant()) {
084                return pp;
085            }
086            GenPolynomial<C> d = PolyUtil.<C> baseDeriviative(pp);
087            d = engine.basePrimitivePart(d);
088            GenPolynomial<C> g = engine.baseGcd(pp, d);
089            g = engine.basePrimitivePart(g);
090            GenPolynomial<C> q = PolyUtil.<C> basePseudoDivide(pp, g);
091            q = engine.basePrimitivePart(q);
092            return q;
093        }
094    
095    
096        /**
097         * GenPolynomial polynomial squarefree factorization.
098         * @param A GenPolynomial.
099         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
100         *         and p_i squarefree.
101         */
102        @Override
103        public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) {
104            SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
105            if (A == null || A.isZERO()) {
106                return sfactors;
107            }
108            if (A.isConstant()) {
109                sfactors.put(A, 1L);
110                return sfactors;
111            }
112            GenPolynomialRing<C> pfac = A.ring;
113            if (pfac.nvar > 1) {
114                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
115            }
116            C ldbcf = A.leadingBaseCoefficient();
117            if (!ldbcf.isONE()) {
118                C cc = engine.baseContent(A);
119                A = A.divide(cc);
120                GenPolynomial<C> f1 = pfac.getONE().multiply(cc);
121                //System.out.println("gcda sqf f1 = " + f1);
122                sfactors.put(f1, 1L);
123            }
124            GenPolynomial<C> T0 = A;
125            GenPolynomial<C> Tp;
126            GenPolynomial<C> T = null;
127            GenPolynomial<C> V = null;
128            long k = 0L;
129            boolean init = true;
130            while (true) {
131                if (init) {
132                    if (T0.isConstant() || T0.isZERO()) {
133                        break;
134                    }
135                    Tp = PolyUtil.<C> baseDeriviative(T0);
136                    T = engine.baseGcd(T0, Tp);
137                    T = engine.basePrimitivePart(T);
138                    V = PolyUtil.<C> basePseudoDivide(T0, T);
139                    //System.out.println("iT0 = " + T0);
140                    //System.out.println("iTp = " + Tp);
141                    //System.out.println("iT  = " + T);
142                    //System.out.println("iV  = " + V);
143                    k = 0L;
144                    init = false;
145                }
146                if (V.isConstant()) {
147                    break;
148                }
149                k++;
150                GenPolynomial<C> W = engine.baseGcd(T, V);
151                W = engine.basePrimitivePart(W);
152                GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W);
153                //System.out.println("W = " + W);
154                //System.out.println("z = " + z);
155                V = W;
156                T = PolyUtil.<C> basePseudoDivide(T, V);
157                //System.out.println("V = " + V);
158                //System.out.println("T = " + T);
159                if (z.degree(0) > 0) {
160                    if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) {
161                        z = engine.basePrimitivePart(z);
162                        logger.info("z,pp = " + z);
163                    }
164                    sfactors.put(z, k);
165                }
166            }
167            return sfactors;
168        }
169    
170    
171        /**
172         * GenPolynomial recursive univariate polynomial greatest squarefree
173         * divisor.
174         * @param P recursive univariate GenPolynomial.
175         * @return squarefree(pp(P)).
176         */
177        @Override
178        public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart(GenPolynomial<GenPolynomial<C>> P) {
179            if (P == null || P.isZERO()) {
180                return P;
181            }
182            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
183            if (pfac.nvar > 1) {
184                throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials");
185            }
186            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
187            // squarefree content
188            GenPolynomial<GenPolynomial<C>> pp = P;
189            GenPolynomial<C> Pc = engine.recursiveContent(P);
190            Pc = engine.basePrimitivePart(Pc);
191            //System.out.println("Pc,bPP = " + Pc);
192            if (!Pc.isONE()) {
193                pp = PolyUtil.<C> coefficientPseudoDivide(pp, Pc);
194                //System.out.println("pp,sqp = " + pp);
195                GenPolynomial<C> Pr = squarefreePart(Pc);
196                Pr = engine.basePrimitivePart(Pr);
197                //System.out.println("Pr,bPP = " + Pr);
198            }
199            if (pp.leadingExpVector().getVal(0) < 1) {
200                //System.out.println("pp = " + pp);
201                //System.out.println("Pc = " + Pc);
202                return pp.multiply(Pc);
203            }
204            GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp);
205            //System.out.println("d = " + d);
206            GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d);
207            //System.out.println("g,rec = " + g);
208            g = engine.baseRecursivePrimitivePart(g);
209            //System.out.println("g,bPP = " + g);
210            GenPolynomial<GenPolynomial<C>> q = PolyUtil.<C> recursivePseudoDivide(pp, g);
211            q = engine.baseRecursivePrimitivePart(q);
212            //System.out.println("q,bPP = " + q);
213            return q.multiply(Pc);
214        }
215    
216    
217        /**
218         * GenPolynomial recursive univariate polynomial squarefree factorization.
219         * @param P recursive univariate GenPolynomial.
220         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
221         *         and p_i squarefree.
222         */
223        @Override
224        public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors(
225                GenPolynomial<GenPolynomial<C>> P) {
226            SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>();
227            if (P == null || P.isZERO()) {
228                return sfactors;
229            }
230            GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
231            if (pfac.nvar > 1) {
232                // recursiveContent not possible by return type
233                throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
234            }
235            // if base coefficient ring is a field, make monic
236            GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
237            C bcc = engine.baseRecursiveContent(P);
238            if (!bcc.isONE()) {
239                GenPolynomial<C> lc = cfac.getONE().multiply(bcc);
240                GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc);
241                sfactors.put(pl, 1L);
242                P = PolyUtil.<C> baseRecursiveDivide(P, bcc);
243            }
244            // factors of content
245            GenPolynomial<C> Pc = engine.recursiveContent(P);
246            if (logger.isInfoEnabled()) {
247                logger.info("Pc = " + Pc);
248            }
249            Pc = engine.basePrimitivePart(Pc);
250            //System.out.println("Pc,PP = " + Pc);
251            if (!Pc.isONE()) {
252                P = PolyUtil.<C> coefficientPseudoDivide(P, Pc);
253            }
254            SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc);
255            if (logger.isInfoEnabled()) {
256                logger.info("rsf = " + rsf);
257            }
258            // add factors of content
259            for (GenPolynomial<C> c : rsf.keySet()) {
260                if (!c.isONE()) {
261                    GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c);
262                    Long rk = rsf.get(c);
263                    sfactors.put(cr, rk);
264                }
265            }
266    
267            // factors of recursive polynomial
268            GenPolynomial<GenPolynomial<C>> T0 = P;
269            GenPolynomial<GenPolynomial<C>> Tp;
270            GenPolynomial<GenPolynomial<C>> T = null;
271            GenPolynomial<GenPolynomial<C>> V = null;
272            long k = 0L;
273            boolean init = true;
274            while (true) {
275                if (init) {
276                    if (T0.isConstant() || T0.isZERO()) {
277                        break;
278                    }
279                    Tp = PolyUtil.<C> recursiveDeriviative(T0);
280                    T = engine.recursiveUnivariateGcd(T0, Tp);
281                    T = engine.baseRecursivePrimitivePart(T);
282                    V = PolyUtil.<C> recursivePseudoDivide(T0, T);
283                    //System.out.println("iT0 = " + T0);
284                    //System.out.println("iTp = " + Tp);
285                    //System.out.println("iT = " + T);
286                    //System.out.println("iV = " + V);
287                    k = 0L;
288                    init = false;
289                }
290                if (V.isConstant()) {
291                    break;
292                }
293                k++;
294                GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V);
295                W = engine.baseRecursivePrimitivePart(W);
296                GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W);
297                //System.out.println("W = " + W);
298                //System.out.println("z = " + z);
299                V = W;
300                T = PolyUtil.<C> recursivePseudoDivide(T, V);
301                //System.out.println("V = " + V);
302                //System.out.println("T = " + T);
303                //was: if ( z.degree(0) > 0 ) {
304                if (!z.isONE() && !z.isZERO()) {
305                    z = engine.baseRecursivePrimitivePart(z);
306                    sfactors.put(z, k);
307                }
308            }
309            return sfactors;
310        }
311    
312    
313        /**
314         * GenPolynomial greatest squarefree divisor.
315         * @param P GenPolynomial.
316         * @return squarefree(pp(P)).
317         */
318        @Override
319        public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) {
320            if (P == null) {
321                throw new IllegalArgumentException(this.getClass().getName() + " P != null");
322            }
323            if (P.isZERO()) {
324                return P;
325            }
326            GenPolynomialRing<C> pfac = P.ring;
327            if (pfac.nvar <= 1) {
328                return baseSquarefreePart(P);
329            }
330            GenPolynomialRing<C> cfac = pfac.contract(1);
331            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
332    
333            GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
334            GenPolynomial<C> Pc = engine.recursiveContent(Pr);
335            Pr = PolyUtil.<C> coefficientPseudoDivide(Pr, Pc);
336            GenPolynomial<C> Ps = squarefreePart(Pc);
337            GenPolynomial<GenPolynomial<C>> PP = recursiveUnivariateSquarefreePart(Pr);
338            GenPolynomial<GenPolynomial<C>> PS = PP.multiply(Ps);
339            GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PS);
340            return D;
341        }
342    
343    
344        /**
345         * GenPolynomial squarefree factorization.
346         * @param P GenPolynomial.
347         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
348         *         and p_i squarefree.
349         */
350        @Override
351        public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) {
352            if (P == null) {
353                throw new IllegalArgumentException(this.getClass().getName() + " P != null");
354            }
355            GenPolynomialRing<C> pfac = P.ring;
356            if (pfac.nvar <= 1) {
357                return baseSquarefreeFactors(P);
358            }
359            SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
360            if (P.isZERO()) {
361                return sfactors;
362            }
363            GenPolynomialRing<C> cfac = pfac.contract(1);
364            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
365    
366            GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
367            SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr);
368    
369            for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) {
370                Long i = m.getValue();
371                GenPolynomial<GenPolynomial<C>> Dr = m.getKey();
372                GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
373                sfactors.put(D, i);
374            }
375            return sfactors;
376        }
377    
378    
379        /**
380         * Coefficients squarefree factorization.
381         * @param P coefficient.
382         * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i}
383         *         and p_i squarefree.
384         */
385        public SortedMap<C, Long> squarefreeFactors(C P) {
386            throw new UnsupportedOperationException("method not implemented");
387        }
388    
389    }