001/*
002 * $Id: GreatestCommonDivisorSimple.java 5774 2017-11-05 17:04:30Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import org.apache.log4j.Logger;
009
010import edu.jas.poly.GenPolynomial;
011import edu.jas.poly.PolyUtil;
012import edu.jas.structure.GcdRingElem;
013import edu.jas.structure.RingFactory;
014
015
016/**
017 * Greatest common divisor algorithms with monic polynomial remainder sequence.
018 * If C is a field, then the monic PRS (on coefficients) is computed otherwise
019 * no simplifications in the reduction are made.
020 * @author Heinz Kredel
021 */
022
023public class GreatestCommonDivisorSimple<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> {
024
025
026    private static final Logger logger = Logger.getLogger(GreatestCommonDivisorSimple.class);
027
028
029    private static final boolean debug = logger.isDebugEnabled();
030
031
032    /**
033     * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for
034     * remainder.
035     * @param P univariate GenPolynomial.
036     * @param S univariate GenPolynomial.
037     * @return gcd(P,S).
038     */
039    @Override
040    public GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
041        if (S == null || S.isZERO()) {
042            return P;
043        }
044        if (P == null || P.isZERO()) {
045            return S;
046        }
047        if (P.ring.nvar > 1) {
048            throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial");
049        }
050        boolean field = P.ring.coFac.isField();
051        long e = P.degree(0);
052        long f = S.degree(0);
053        GenPolynomial<C> q;
054        GenPolynomial<C> r;
055        if (f > e) {
056            r = P;
057            q = S;
058            long g = f;
059            f = e;
060            e = g;
061        } else {
062            q = P;
063            r = S;
064        }
065        if (debug) {
066            logger.debug("degrees: e = " + e + ", f = " + f);
067        }
068        C c;
069        if (field) {
070            r = r.monic();
071            q = q.monic();
072            c = P.ring.getONECoefficient();
073        } else {
074            r = r.abs();
075            q = q.abs();
076            C a = baseContent(r);
077            C b = baseContent(q);
078            c = gcd(a, b); // indirection
079            r = divide(r, a); // indirection
080            q = divide(q, b); // indirection
081        }
082        if (r.isONE()) {
083            return r.multiply(c);
084        }
085        if (q.isONE()) {
086            return q.multiply(c);
087        }
088        GenPolynomial<C> x;
089        //System.out.println("q = " + q);
090        //System.out.println("r = " + r);
091        while (!r.isZERO()) {
092            x = PolyUtil.<C> baseSparsePseudoRemainder(q, r);
093            q = r;
094            if (field) {
095                r = x.monic();
096            } else {
097                r = x;
098            }
099            //System.out.println("q = " + q);
100            //System.out.println("r = " + r);
101        }
102        q = basePrimitivePart(q);
103        return (q.multiply(c)).abs();
104    }
105
106
107    /**
108     * Univariate GenPolynomial recursive greatest comon divisor. Uses
109     * pseudoRemainder for remainder.
110     * @param P univariate recursive GenPolynomial.
111     * @param S univariate recursive GenPolynomial.
112     * @return gcd(P,S).
113     */
114    @Override
115    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P,
116                    GenPolynomial<GenPolynomial<C>> S) {
117        if (S == null || S.isZERO()) {
118            return P;
119        }
120        if (P == null || P.isZERO()) {
121            return S;
122        }
123        if (P.ring.nvar > 1) {
124            throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial");
125        }
126        boolean field = P.leadingBaseCoefficient().ring.coFac.isField();
127        long e = P.degree(0);
128        long f = S.degree(0);
129        GenPolynomial<GenPolynomial<C>> q;
130        GenPolynomial<GenPolynomial<C>> r;
131        if (f > e) {
132            r = P;
133            q = S;
134            long g = f;
135            f = e;
136            e = g;
137        } else {
138            q = P;
139            r = S;
140        }
141        if (debug) {
142            logger.debug("degrees: e = " + e + ", f = " + f);
143        }
144        if (field) {
145            r = PolyUtil.<C> monic(r);
146            q = PolyUtil.<C> monic(q);
147        } else {
148            r = r.abs();
149            q = q.abs();
150        }
151        GenPolynomial<C> a = recursiveContent(r);
152        GenPolynomial<C> b = recursiveContent(q);
153
154        GenPolynomial<C> c = gcd(a, b); // go to recursion
155        //System.out.println("rgcd c = " + c);
156        r = PolyUtil.<C> recursiveDivide(r, a);
157        q = PolyUtil.<C> recursiveDivide(q, b);
158        if (r.isONE()) {
159            return r.multiply(c);
160        }
161        if (q.isONE()) {
162            return q.multiply(c);
163        }
164        GenPolynomial<GenPolynomial<C>> x;
165        while (!r.isZERO()) {
166            x = PolyUtil.<C> recursivePseudoRemainder(q, r);
167            if (logger.isDebugEnabled()) {
168                logger.info("recursivePseudoRemainder.bits = " + x.bitLength());
169            }
170            q = r;
171            if (field) {
172                r = PolyUtil.<C> monic(x);
173            } else {
174                r = x;
175            }
176        }
177        q = recursivePrimitivePart(q);
178        q = q.abs().multiply(c);
179        return q;
180    }
181
182
183    /**
184     * Univariate GenPolynomial resultant.
185     * @param P univariate GenPolynomial.
186     * @param S univariate GenPolynomial.
187     * @return res(P,S).
188     */
189    @Override
190    public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) {
191        if (S == null || S.isZERO()) {
192            return S;
193        }
194        if (P == null || P.isZERO()) {
195            return P;
196        }
197        if (P.ring.nvar > 1 || P.ring.nvar == 0) {
198            throw new IllegalArgumentException("no univariate polynomial");
199        }
200        long e = P.degree(0);
201        long f = S.degree(0);
202        if (f == 0 && e == 0) {
203            return P.ring.getONE();
204        }
205        if (e == 0) {
206            return P.power(f);
207        }
208        if (f == 0) {
209            return S.power(e);
210        }
211        GenPolynomial<C> q;
212        GenPolynomial<C> r;
213        int s = 0; // sign is +, 1 for sign is -
214        if (e < f) {
215            r = P;
216            q = S;
217            long t = e;
218            e = f;
219            f = t;
220            if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f)
221                s = 1;
222            }
223        } else {
224            q = P;
225            r = S;
226        }
227        RingFactory<C> cofac = P.ring.coFac;
228        boolean field = cofac.isField();
229        C c = cofac.getONE();
230        GenPolynomial<C> x;
231        long g;
232        do {
233            if (field) {
234                x = q.remainder(r);
235            } else {
236                x = PolyUtil.<C> baseSparsePseudoRemainder(q, r);
237                //System.out.println("x_s = " + x + ", lbcf(r) = " + r.leadingBaseCoefficient());
238            }
239            if (x.isZERO()) {
240                return x;
241            }
242            //System.out.println("x = " + x);
243            e = q.degree(0);
244            f = r.degree(0);
245            if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f)
246                s = 1 - s;
247            }
248            g = x.degree(0);
249            C c2 = r.leadingBaseCoefficient();
250            for (int i = 0; i < (e - g); i++) {
251                c = c.multiply(c2);
252            }
253            q = r;
254            r = x;
255        } while (g != 0);
256        C c2 = r.leadingBaseCoefficient();
257        for (int i = 0; i < f; i++) {
258            c = c.multiply(c2);
259        }
260        if (s == 1) {
261            c = c.negate();
262        }
263        x = P.ring.getONE().multiply(c);
264        return x;
265    }
266
267
268    /**
269     * Univariate GenPolynomial recursive resultant.
270     * @param P univariate recursive GenPolynomial.
271     * @param S univariate recursive GenPolynomial.
272     * @return res(P,S).
273     */
274    @Override
275    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P,
276                    GenPolynomial<GenPolynomial<C>> S) {
277        if (S == null || S.isZERO()) {
278            return S;
279        }
280        if (P == null || P.isZERO()) {
281            return P;
282        }
283        if (P.ring.nvar > 1 || P.ring.nvar == 0) {
284            throw new IllegalArgumentException("no recursive univariate polynomial");
285        }
286        long e = P.degree(0);
287        long f = S.degree(0);
288        if (f == 0 && e == 0) {
289            // if coeffs are multivariate (and non constant)
290            // otherwise it would be 1
291            GenPolynomial<C> t = resultant(P.leadingBaseCoefficient(), S.leadingBaseCoefficient());
292            return P.ring.getONE().multiply(t);
293        }
294        if (e == 0) {
295            return P.power(f);
296        }
297        if (f == 0) {
298            return S.power(e);
299        }
300        GenPolynomial<GenPolynomial<C>> q;
301        GenPolynomial<GenPolynomial<C>> r;
302        int s = 0; // sign is +, 1 for sign is -
303        if (f > e) {
304            r = P;
305            q = S;
306            long g = f;
307            f = e;
308            e = g;
309            if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f)
310                s = 1;
311            }
312        } else {
313            q = P;
314            r = S;
315        }
316        GenPolynomial<GenPolynomial<C>> x;
317        RingFactory<GenPolynomial<C>> cofac = P.ring.coFac;
318        GenPolynomial<C> c = cofac.getONE();
319        long g;
320        do {
321            x = PolyUtil.<C> recursiveSparsePseudoRemainder(q, r);
322            //x = PolyUtil.<C>recursiveDensePseudoRemainder(q,r);
323            if (x.isZERO()) {
324                return x;
325            }
326            //no: x = recursivePrimitivePart(x);
327            //System.out.println("x = " + x);
328            e = q.degree(0);
329            f = r.degree(0);
330            if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f)
331                s = 1 - s;
332            }
333            g = x.degree(0);
334            GenPolynomial<C> c2 = r.leadingBaseCoefficient();
335            for (int i = 0; i < (e - g); i++) {
336                c = c.multiply(c2);
337            }
338            q = r;
339            r = x;
340        } while (g != 0);
341        GenPolynomial<C> c2 = r.leadingBaseCoefficient();
342        for (int i = 0; i < f; i++) {
343            c = c.multiply(c2);
344        }
345        if (s == 1) {
346            c = c.negate();
347        }
348        x = P.ring.getONE().multiply(c);
349        return x;
350    }
351
352}