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