001/*
002 * $Id: PolyModUtil.java 5611 2016-10-03 22:06:32Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.gb.SolvableGroebnerBaseAbstract;
014import edu.jas.gb.SolvableGroebnerBaseSeq;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.poly.GenPolynomialRing;
017import edu.jas.poly.GenSolvablePolynomial;
018import edu.jas.poly.GenSolvablePolynomialRing;
019import edu.jas.poly.PolyUtil;
020import edu.jas.structure.GcdRingElem;
021
022
023/**
024 * Package gb and gbufd utilities.
025 * @author Heinz Kredel
026 */
027
028public class PolyModUtil {
029
030
031    private static final Logger logger = Logger.getLogger(PolyModUtil.class);
032
033
034    private static final boolean debug = logger.isDebugEnabled();
035
036
037    /**
038     * Least common multiple via ideal intersection.
039     * @param r solvable polynomial ring.
040     * @param n first solvable polynomial.
041     * @param d second solvable polynomial.
042     * @return lcm(n,d)
043     */
044    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzLcm(GenSolvablePolynomialRing<C> r,
045                    GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) {
046        if (n.isZERO()) {
047            return n;
048        }
049        if (d.isZERO()) {
050            return d;
051        }
052        if (n.isONE()) {
053            return d;
054        }
055        if (d.isONE()) {
056            return n;
057        }
058        List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(1);
059        A.add(n);
060        List<GenSolvablePolynomial<C>> B = new ArrayList<GenSolvablePolynomial<C>>(1);
061        B.add(d);
062        List<GenSolvablePolynomial<C>> c = PolyGBUtil.<C> intersect(r, A, B);
063        //if (c.size() != 1) {
064        // SolvableSyzygyAbstract<C> sz = new SolvableSyzygyAbstract<C>();
065        // GenSolvablePolynomial<C>[] oc = sz.leftOreCond(n,d);
066        // GenSolvablePolynomial<C> nc = oc[0].multiply(n);
067        // System.out.println("nc = " + nc);
068        // return nc;
069        //}
070        GenSolvablePolynomial<C> lcm = null;
071        for (GenSolvablePolynomial<C> p : c) {
072            if (p == null || p.isZERO()) {
073                continue;
074            }
075            //System.out.println("p = " + p);
076            if (lcm == null) {
077                lcm = p;
078                continue;
079            }
080            if (lcm.compareTo(p) > 0) {
081                lcm = p;
082            }
083        }
084        if (lcm == null) {
085            throw new RuntimeException("this cannot happen: lcm == null: " + c);
086        }
087        return lcm;
088    }
089
090
091    /**
092     * Greatest common divisor via least common multiple.
093     * @param r solvable polynomial ring.
094     * @param n first solvable polynomial.
095     * @param d second solvable polynomial.
096     * @return gcd(n,d)
097     */
098    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzGcd(GenSolvablePolynomialRing<C> r,
099                    GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) {
100        return syzLeftGcd(r, n, d);
101    }
102
103
104    /**
105     * Left greatest common divisor via least common multiple.
106     * @param r solvable polynomial ring.
107     * @param n first solvable polynomial.
108     * @param d second solvable polynomial.
109     * @return gcd(n,d)
110     */
111    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzLeftGcd(
112                    GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) {
113
114        if (n.isZERO()) {
115            return d;
116        }
117        if (d.isZERO()) {
118            return n;
119        }
120        if (n.isConstant()) {
121            return r.getONE();
122        }
123        if (d.isConstant()) {
124            return r.getONE();
125        }
126        if (n.totalDegree() > 3 || d.totalDegree() > 3) { // how avoid too long running GBs ?
127            //if (n.totalDegree() + d.totalDegree() > 6) { // how avoid too long running GBs ?
128            // && n.length() < 10 && d.length() < 10
129            logger.warn("skipping GB computation: degs = " + n.totalDegree() + ", " + d.totalDegree());
130            return r.getONE();
131        }
132        List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(2);
133        A.add(n);
134        A.add(d);
135        SolvableGroebnerBaseAbstract<C> sbb = new SolvableGroebnerBaseSeq<C>();
136        logger.warn("left syzGcd computing GB: " + A);
137        List<GenSolvablePolynomial<C>> G = sbb.rightGB(A); //not: leftGB, not: sbb.twosidedGB(A);
138        if (debug) {
139            logger.info("G = " + G);
140        }
141        if (G.size() == 1) {
142            return G.get(0);
143        }
144        logger.warn("gcd not determined, set to 1: " + G); // + ", A = " + A);
145        return r.getONE();
146    }
147
148
149    /**
150     * Right greatest common divisor via least common multiple.
151     * @param r solvable polynomial ring.
152     * @param n first solvable polynomial.
153     * @param d second solvable polynomial.
154     * @return gcd(n,d)
155     */
156    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzRightGcd(
157                    GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) {
158
159        if (n.isZERO()) {
160            return d;
161        }
162        if (d.isZERO()) {
163            return n;
164        }
165        if (n.isConstant()) {
166            return r.getONE();
167        }
168        if (d.isConstant()) {
169            return r.getONE();
170        }
171        if (n.totalDegree() > 3 || d.totalDegree() > 3) { // how avoid too long running GBs ?
172            //if (n.totalDegree() + d.totalDegree() > 6) { // how avoid too long running GBs ?
173            // && n.length() < 10 && d.length() < 10
174            logger.warn("skipping GB computation: degs = " + n.totalDegree() + ", " + d.totalDegree());
175            return r.getONE();
176        }
177        List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(2);
178        A.add(n);
179        A.add(d);
180        SolvableGroebnerBaseAbstract<C> sbb = new SolvableGroebnerBaseSeq<C>();
181        logger.warn("right syzGcd computing GB: " + A);
182        List<GenSolvablePolynomial<C>> G = sbb.leftGB(A); // not: sbb.twosidedGB(A);
183        if (debug) {
184            logger.info("G = " + G);
185        }
186        if (G.size() == 1) {
187            return G.get(0);
188        }
189        logger.warn("gcd not determined, set to 1: " + G); // + ", A = " + A);
190        return r.getONE();
191    }
192
193
194    /**
195     * Greatest common divisor and cofactors via least common multiple and
196     * reduction.
197     * @param r solvable polynomial ring.
198     * @param n first solvable polynomial.
199     * @param d second solvable polynomial.
200     * @return [ g=gcd(n,d), n/g, d/g ]
201     */
202    @SuppressWarnings({ "unchecked", "cast" })
203    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C>[] syzGcdCofactors(
204                    GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) {
205        GenSolvablePolynomial<C>[] res = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[3];
206        res[0] = PolyModUtil.<C> syzGcd(r, n, d);
207        res[1] = n;
208        res[2] = d;
209        if (res[0].isONE()) {
210            return res;
211        }
212        GenSolvablePolynomial<C>[] nqr = PolyGBUtil.<C> quotientRemainder(n, res[0]);
213        if (!nqr[1].isZERO()) {
214            res[0] = r.getONE();
215            return res;
216        }
217        GenSolvablePolynomial<C>[] dqr = PolyGBUtil.<C> quotientRemainder(d, res[0]);
218        if (!dqr[1].isZERO()) {
219            res[0] = r.getONE();
220            return res;
221        }
222        res[1] = nqr[0];
223        res[2] = dqr[0];
224        return res;
225    }
226
227
228    /**
229     * Least common multiple. Just for fun, is not efficient.
230     * @param r polynomial ring.
231     * @param n first polynomial.
232     * @param d second polynomial.
233     * @return lcm(n,d)
234     */
235    public static <C extends GcdRingElem<C>> GenPolynomial<C> syzLcm(GenPolynomialRing<C> r,
236                    GenPolynomial<C> n, GenPolynomial<C> d) {
237        List<GenPolynomial<C>> A = new ArrayList<GenPolynomial<C>>(1);
238        A.add(n);
239        List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(1);
240        B.add(d);
241        List<GenPolynomial<C>> c = PolyGBUtil.<C> intersect(r, A, B);
242        if (c.size() != 1) {
243            logger.warn("lcm not uniqe: " + c);
244            //throw new RuntimeException("lcm not uniqe: " + c);
245        }
246        GenPolynomial<C> lcm = c.get(0);
247        return lcm;
248    }
249
250
251    /**
252     * Greatest common divisor. Just for fun, is not efficient.
253     * @param r polynomial ring.
254     * @param n first polynomial.
255     * @param d second polynomial.
256     * @return gcd(n,d)
257     */
258    public static <C extends GcdRingElem<C>> GenPolynomial<C> syzGcd(GenPolynomialRing<C> r,
259                    GenPolynomial<C> n, GenPolynomial<C> d) {
260        if (n.isZERO()) {
261            return d;
262        }
263        if (d.isZERO()) {
264            return n;
265        }
266        if (n.isONE()) {
267            return n;
268        }
269        if (d.isONE()) {
270            return d;
271        }
272        GenPolynomial<C> p = n.multiply(d);
273        GenPolynomial<C> lcm = syzLcm(r, n, d);
274        GenPolynomial<C> gcd = PolyUtil.<C> basePseudoDivide(p, lcm);
275        return gcd;
276    }
277
278
279}