001/*
002 * $Id$
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.Map;
009import java.util.SortedMap;
010import java.util.TreeMap;
011
012import org.apache.logging.log4j.LogManager;
013import org.apache.logging.log4j.Logger;
014
015import edu.jas.poly.ExpVector;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.poly.PolyUtil;
019import edu.jas.structure.GcdRingElem;
020import edu.jas.structure.RingFactory;
021
022
023/**
024 * Squarefree decomposition for coefficient fields of characteristic 0,
025 * algorithm of Yun.
026 * @author Heinz Kredel
027 */
028
029public class SquarefreeFieldChar0Yun<C extends GcdRingElem<C>> extends SquarefreeFieldChar0<C> {
030
031
032    private static final Logger logger = LogManager.getLogger(SquarefreeFieldChar0Yun.class);
033
034
035    //private static final boolean debug = logger.isDebugEnabled();
036
037
038    /**
039     * Constructor.
040     */
041    public SquarefreeFieldChar0Yun(RingFactory<C> fac) {
042        super(fac);
043    }
044
045
046    /**
047     * Get the String representation.
048     * @see java.lang.Object#toString()
049     */
050    @Override
051    public String toString() {
052        return getClass().getName() + " with " + engine + " over " + coFac;
053    }
054
055
056    /**
057     * GenPolynomial polynomial squarefree factorization.
058     * @param A GenPolynomial.
059     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with A = prod_{i=1,...,k}
060     *         p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j.
061     */
062    @Override
063    public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) {
064        SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>();
065        if (A == null || A.isZERO()) {
066            return sfactors;
067        }
068        if (A.isConstant()) {
069            sfactors.put(A, 1L);
070            return sfactors;
071        }
072        GenPolynomialRing<C> pfac = A.ring;
073        if (pfac.nvar > 1) {
074            throw new IllegalArgumentException(
075                            this.getClass().getName() + " only for univariate polynomials");
076        }
077        C ldbcf = A.leadingBaseCoefficient();
078        if (!ldbcf.isONE()) {
079            A = A.divide(ldbcf);
080            GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf);
081            //System.out.println("gcda sqf f1 = " + f1);
082            sfactors.put(f1, 1L);
083            ldbcf = pfac.coFac.getONE();
084        }
085        // divide by trailing term
086        ExpVector et = A.trailingExpVector();
087        if (!et.isZERO()) {
088            GenPolynomial<C> tr = pfac.valueOf(et);
089            if (logger.isInfoEnabled()) {
090                logger.info("trailing term = " + tr);
091            }
092            A = PolyUtil.<C> basePseudoDivide(A, tr);
093            long ep = et.getVal(0); // univariate
094            et = et.subst(0, 1);
095            tr = pfac.valueOf(et);
096            if (logger.isInfoEnabled()) {
097                logger.info("tr, ep = " + tr + ", " + ep);
098            }
099            sfactors.put(tr, ep);
100            if (A.length() == 1) {
101                return sfactors;
102            }
103        }
104        GenPolynomial<C> Tp, T, W, Y, Z;
105        long k = 1L; //0L
106        Tp = PolyUtil.<C> baseDeriviative(A);
107        T = engine.baseGcd(A, Tp);
108        T = T.monic();
109        if (T.isConstant()) {
110            sfactors.put(A, k);
111            return sfactors;
112        }
113        W = PolyUtil.<C> basePseudoDivide(A, T);
114        //if (W.isConstant()) {
115        //    return sfactors;
116        //}
117        Y = PolyUtil.<C> basePseudoDivide(Tp, T);
118        GenPolynomial<C> Wp = PolyUtil.<C> baseDeriviative(W);
119        Z = Y.subtract(Wp);
120        while (!Z.isZERO()) {
121            GenPolynomial<C> g = engine.baseGcd(W, Z);
122            g = g.monic();
123            if (!g.isONE()) {
124                sfactors.put(g, k);
125            }
126            W = PolyUtil.<C> basePseudoDivide(W, g);
127            //System.out.println("W = " + W);
128            //System.out.println("g = " + g);
129            Y = PolyUtil.<C> basePseudoDivide(Z, g);
130            Wp = PolyUtil.<C> baseDeriviative(W);
131            Z = Y.subtract(Wp);
132            k++;
133        }
134        logger.info("W, k = " + W + ", " + k);
135        if (!W.isONE()) {
136            sfactors.put(W, k);
137        }
138        return normalizeFactorization(sfactors);
139    }
140
141
142    /**
143     * GenPolynomial recursive univariate polynomial squarefree factorization.
144     * @param P recursive univariate GenPolynomial.
145     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
146     *         p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j.
147     */
148    @Override
149    public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors(
150                    GenPolynomial<GenPolynomial<C>> P) {
151        SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>();
152        if (P == null || P.isZERO()) {
153            return sfactors;
154        }
155        GenPolynomialRing<GenPolynomial<C>> pfac = P.ring;
156        if (pfac.nvar > 1) {
157            // recursiveContent not possible by return type
158            throw new IllegalArgumentException(
159                            this.getClass().getName() + " only for univariate polynomials");
160        }
161        // if base coefficient ring is a field, make monic
162        GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac;
163        C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
164        if (!ldbcf.isONE()) {
165            GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf);
166            GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc);
167            sfactors.put(pl, 1L);
168            C li = ldbcf.inverse();
169            //System.out.println("li = " + li);
170            P = P.multiply(cfac.getONE().multiply(li));
171            //System.out.println("P,monic = " + P);
172            ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
173        }
174        // factors of content
175        GenPolynomial<C> Pc = engine.recursiveContent(P);
176        if (logger.isInfoEnabled()) {
177            logger.info("recursiveContent = " + Pc);
178        }
179        Pc = Pc.monic();
180        if (!Pc.isONE()) {
181            P = PolyUtil.<C> coefficientPseudoDivide(P, Pc);
182        }
183        SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc);
184        if (logger.isInfoEnabled()) {
185            logger.info("squarefreeFactors = " + rsf);
186        }
187        // add factors of content
188        for (Map.Entry<GenPolynomial<C>, Long> me : rsf.entrySet()) {
189            GenPolynomial<C> c = me.getKey();
190            if (!c.isONE()) {
191                GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c);
192                Long rk = me.getValue();
193                sfactors.put(cr, rk);
194            }
195        }
196        // divide by trailing term
197        ExpVector et = P.trailingExpVector();
198        if (!et.isZERO()) {
199            GenPolynomial<GenPolynomial<C>> tr = pfac.valueOf(et);
200            if (logger.isInfoEnabled()) {
201                logger.info("trailing term = " + tr);
202            }
203            P = PolyUtil.<C> recursivePseudoDivide(P, tr);
204            long ep = et.getVal(0); // univariate
205            et = et.subst(0, 1);
206            tr = pfac.valueOf(et);
207            sfactors.put(tr, ep);
208            //P.length == 1 ??
209        }
210        // factors of recursive polynomial
211        GenPolynomial<GenPolynomial<C>> Tp, T, W, Y, Z;
212        long k = 1L; //0L
213        Tp = PolyUtil.<C> recursiveDeriviative(P);
214        T = engine.recursiveUnivariateGcd(P, Tp);
215        T = PolyUtil.<C> monic(T);
216        if (T.isConstant()) {
217            sfactors.put(P, k);
218            return sfactors;
219        }
220        W = PolyUtil.<C> recursivePseudoDivide(P, T);
221        //if (W.isConstant()) {
222        //    return sfactors;
223        //}
224        Y = PolyUtil.<C> recursivePseudoDivide(Tp, T);
225        GenPolynomial<GenPolynomial<C>> Wp = PolyUtil.<C> recursiveDeriviative(W);
226        Z = Y.subtract(Wp);
227
228        while (!Z.isZERO()) {
229            GenPolynomial<GenPolynomial<C>> g = engine.recursiveGcd(W, Z);
230            g = PolyUtil.<C> monic(g);
231            if (!g.isONE()) {
232                sfactors.put(g, k);
233            }
234            W = PolyUtil.<C> recursivePseudoDivide(W, g);
235            //System.out.println("W = " + W);
236            //System.out.println("g = " + g);
237            Y = PolyUtil.<C> recursivePseudoDivide(Z, g);
238            Wp = PolyUtil.<C> recursiveDeriviative(W);
239            Z = Y.subtract(Wp);
240            k++;
241        }
242        logger.info("W, k = " + W + ", " + k);
243        if (!W.isONE()) {
244            sfactors.put(W, k);
245        }
246        return sfactors; //normalizeFactorization(sfactors);
247    }
248
249}