001/*
002 * $Id: Quotient.java 5997 2020-03-17 15:34:31Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import org.apache.logging.log4j.LogManager;
009import org.apache.logging.log4j.Logger;
010
011import edu.jas.kern.PrettyPrint;
012import edu.jas.poly.GenPolynomial;
013import edu.jas.structure.GcdRingElem;
014import edu.jas.structure.QuotPair;
015
016
017/**
018 * Quotient, that is a rational function, based on GenPolynomial with RingElem
019 * interface. Objects of this class are immutable.
020 * @author Heinz Kredel
021 */
022public class Quotient<C extends GcdRingElem<C>>
023                implements GcdRingElem<Quotient<C>>, QuotPair<GenPolynomial<C>> {
024
025
026    private static final Logger logger = LogManager.getLogger(Quotient.class);
027
028
029    private static final boolean debug = logger.isDebugEnabled();
030
031
032    /**
033     * Quotient class factory data structure.
034     */
035    public final QuotientRing<C> ring;
036
037
038    /**
039     * Numerator part of the element data structure.
040     */
041    public final GenPolynomial<C> num;
042
043
044    /**
045     * Denominator part of the element data structure.
046     */
047    public final GenPolynomial<C> den;
048
049
050    /**
051     * The constructor creates a Quotient object from a ring factory.
052     * @param r ring factory.
053     */
054    public Quotient(QuotientRing<C> r) {
055        this(r, r.ring.getZERO());
056    }
057
058
059    /**
060     * The constructor creates a Quotient object from a ring factory and a
061     * numerator polynomial. The denominator is assumed to be 1.
062     * @param r ring factory.
063     * @param n numerator polynomial.
064     */
065    public Quotient(QuotientRing<C> r, GenPolynomial<C> n) {
066        this(r, n, r.ring.getONE(), true);
067    }
068
069
070    /**
071     * The constructor creates a Quotient object from a ring factory and a
072     * numerator and denominator polynomial.
073     * @param r ring factory.
074     * @param n numerator polynomial.
075     * @param d denominator polynomial.
076     */
077    public Quotient(QuotientRing<C> r, GenPolynomial<C> n, GenPolynomial<C> d) {
078        this(r, n, d, false);
079    }
080
081
082    /**
083     * The constructor creates a Quotient object from a ring factory and a
084     * numerator and denominator polynomial.
085     * @param r ring factory.
086     * @param n numerator polynomial.
087     * @param d denominator polynomial.
088     * @param isred true if gcd(n,d) == 1, else false.
089     */
090    protected Quotient(QuotientRing<C> r, GenPolynomial<C> n, GenPolynomial<C> d, boolean isred) {
091        if (d == null || d.isZERO()) {
092            throw new IllegalArgumentException("denominator may not be zero");
093        }
094        ring = r;
095        if (d.signum() < 0) {
096            n = n.negate();
097            d = d.negate();
098        }
099        if (!isred) {
100            // must reduce to lowest terms
101            GenPolynomial<C> gcd = ring.gcd(n, d);
102            if (false || debug) {
103                logger.info("gcd = " + gcd);
104            }
105            //GenPolynomial<C> gcd = ring.ring.getONE();
106            if (!gcd.isONE()) {
107                //logger.info("gcd = " + gcd);
108                n = ring.divide(n, gcd);
109                d = ring.divide(d, gcd);
110            }
111        }
112        C lc = d.leadingBaseCoefficient();
113        if (!lc.isONE() && lc.isUnit()) {
114            lc = lc.inverse();
115            n = n.multiply(lc);
116            d = d.multiply(lc);
117        }
118        num = n;
119        den = d;
120    }
121
122
123    /**
124     * Get the corresponding element factory.
125     * @return factory for this Element.
126     * @see edu.jas.structure.Element#factory()
127     */
128    public QuotientRing<C> factory() {
129        return ring;
130    }
131
132
133    /**
134     * Numerator.
135     * @see edu.jas.structure.QuotPair#numerator()
136     */
137    public GenPolynomial<C> numerator() {
138        return num;
139    }
140
141
142    /**
143     * Denominator.
144     * @see edu.jas.structure.QuotPair#denominator()
145     */
146    public GenPolynomial<C> denominator() {
147        return den;
148    }
149
150
151    /**
152     * Clone this.
153     * @see java.lang.Object#clone()
154     */
155    @Override
156    public Quotient<C> copy() {
157        return new Quotient<C>(ring, num, den, true);
158    }
159
160
161    /**
162     * Is Quotient zero.
163     * @return If this is 0 then true is returned, else false.
164     * @see edu.jas.structure.RingElem#isZERO()
165     */
166    public boolean isZERO() {
167        return num.isZERO();
168    }
169
170
171    /**
172     * Is Quotient one.
173     * @return If this is 1 then true is returned, else false.
174     * @see edu.jas.structure.RingElem#isONE()
175     */
176    public boolean isONE() {
177        return num.equals(den);
178    }
179
180
181    /**
182     * Is Quotient a unit.
183     * @return If this is a unit then true is returned, else false.
184     * @see edu.jas.structure.RingElem#isUnit()
185     */
186    public boolean isUnit() {
187        if (num.isZERO()) {
188            return false;
189        }
190        return true;
191    }
192
193
194    /**
195     * Is Qoutient a constant.
196     * @return true, if this has constant numerator and denominator, else false.
197     */
198    public boolean isConstant() {
199        return num.isConstant() && den.isConstant();
200    }
201
202
203    /**
204     * Get the String representation as RingElem.
205     * @see java.lang.Object#toString()
206     */
207    @Override
208    public String toString() {
209        if (PrettyPrint.isTrue()) {
210            String s = "{ " + num.toString(ring.ring.getVars());
211            if (!den.isONE()) {
212                s += " | " + den.toString(ring.ring.getVars());
213            }
214            return s + " }";
215        }
216        return "Quotient[ " + num.toString() + " | " + den.toString() + " ]";
217    }
218
219
220    /**
221     * Get a scripting compatible string representation.
222     * @return script compatible representation for this Element.
223     * @see edu.jas.structure.Element#toScript()
224     */
225    @Override
226    public String toScript() {
227        // Python case
228        if (den.isONE()) {
229            return num.toScript();
230        }
231        if (den.length() == 1 && den.totalDegree() > 1) {
232            return num.toScript() + " / (" + den.toScript() + " )";
233        }
234        return num.toScript() + " / " + den.toScript();
235    }
236
237
238    /**
239     * Get a scripting compatible string representation of the factory.
240     * @return script compatible representation for this ElemFactory.
241     * @see edu.jas.structure.Element#toScriptFactory()
242     */
243    @Override
244    public String toScriptFactory() {
245        // Python case
246        return factory().toScript();
247    }
248
249
250    /**
251     * Quotient comparison.
252     * @param b Quotient.
253     * @return sign(this-b).
254     */
255    @Override
256    public int compareTo(Quotient<C> b) {
257        if (b == null || b.isZERO()) {
258            return this.signum();
259        }
260        if (this.isZERO()) {
261            return -b.signum();
262        }
263        // assume sign(den,b.den) > 0
264        int s1 = num.signum();
265        int s2 = b.num.signum();
266        int t = (s1 - s2) / 2;
267        if (t != 0) {
268            return t;
269        }
270        if (den.compareTo(b.den) == 0) {
271            return num.compareTo(b.num);
272        }
273        GenPolynomial<C> r = num.multiply(b.den);
274        GenPolynomial<C> s = den.multiply(b.num);
275        return r.compareTo(s);
276    }
277
278
279    /**
280     * Comparison with any other object.
281     * @see java.lang.Object#equals(java.lang.Object)
282     */
283    @SuppressWarnings("unchecked")
284    @Override
285    public boolean equals(Object b) {
286        if (b == null) {
287            return false;
288        }
289        if (!(b instanceof Quotient)) {
290            return false;
291        }
292        Quotient<C> a = (Quotient<C>) b;
293        return compareTo(a) == 0;
294        //return num.equals(a.num) && den.equals(a.den);
295    }
296
297
298    /**
299     * Hash code for this quotient.
300     * @see java.lang.Object#hashCode()
301     */
302    @Override
303    public int hashCode() {
304        int h;
305        h = ring.hashCode();
306        h = 37 * h + num.hashCode();
307        h = 37 * h + den.hashCode();
308        return h;
309    }
310
311
312    /**
313     * Quotient absolute value.
314     * @return the absolute value of this.
315     * @see edu.jas.structure.RingElem#abs()
316     */
317    public Quotient<C> abs() {
318        return new Quotient<C>(ring, num.abs(), den, true);
319    }
320
321
322    /**
323     * Quotient summation.
324     * @param S Quotient.
325     * @return this+S.
326     */
327    public Quotient<C> sum(Quotient<C> S) {
328        if (S == null || S.isZERO()) {
329            return this;
330        }
331        if (this.isZERO()) {
332            return S;
333        }
334        GenPolynomial<C> n;
335        if (den.isONE() && S.den.isONE()) {
336            n = num.sum(S.num);
337            return new Quotient<C>(ring, n);
338        }
339        if (den.isONE()) {
340            n = num.multiply(S.den);
341            n = n.sum(S.num);
342            return new Quotient<C>(ring, n, S.den, false);
343        }
344        if (S.den.isONE()) {
345            n = S.num.multiply(den);
346            n = n.sum(num);
347            return new Quotient<C>(ring, n, den, false);
348        }
349        if (den.compareTo(S.den) == 0) {
350            n = num.sum(S.num);
351            return new Quotient<C>(ring, n, den, false);
352        }
353        GenPolynomial<C> d;
354        GenPolynomial<C> sd;
355        GenPolynomial<C> g;
356        g = ring.gcd(den, S.den);
357        if (g.isONE()) {
358            d = den;
359            sd = S.den;
360        } else {
361            d = ring.divide(den, g);
362            sd = ring.divide(S.den, g);
363        }
364        n = num.multiply(sd);
365        n = n.sum(d.multiply(S.num));
366        if (n.isZERO()) {
367            return ring.getZERO();
368        }
369        GenPolynomial<C> f;
370        GenPolynomial<C> dd;
371        dd = den;
372        if (!g.isONE()) {
373            f = ring.gcd(n, g);
374            if (!f.isONE()) {
375                n = ring.divide(n, f);
376                dd = ring.divide(den, f);
377            }
378        }
379        d = dd.multiply(sd);
380        return new Quotient<C>(ring, n, d, true);
381    }
382
383
384    /**
385     * Quotient negate.
386     * @return -this.
387     * @see edu.jas.structure.RingElem#negate()
388     */
389    public Quotient<C> negate() {
390        return new Quotient<C>(ring, num.negate(), den, true);
391    }
392
393
394    /**
395     * Quotient signum.
396     * @see edu.jas.structure.RingElem#signum()
397     * @return signum(this).
398     */
399    public int signum() {
400        // assume sign(den) > 0
401        return num.signum();
402    }
403
404
405    /**
406     * Quotient subtraction.
407     * @param S Quotient.
408     * @return this-S.
409     */
410    public Quotient<C> subtract(Quotient<C> S) {
411        return sum(S.negate());
412    }
413
414
415    /**
416     * Quotient division.
417     * @param S Quotient.
418     * @return this/S.
419     */
420    public Quotient<C> divide(Quotient<C> S) {
421        return multiply(S.inverse());
422    }
423
424
425    /**
426     * Quotient inverse.
427     * @see edu.jas.structure.RingElem#inverse()
428     * @return S with S = 1/this.
429     */
430    public Quotient<C> inverse() {
431        if (num.isZERO()) {
432            throw new ArithmeticException("element not invertible " + this);
433        }
434        return new Quotient<C>(ring, den, num, true);
435    }
436
437
438    /**
439     * Quotient remainder.
440     * @param S Quotient.
441     * @return this - (this/S)*S.
442     */
443    public Quotient<C> remainder(Quotient<C> S) {
444        if (S.isZERO()) {
445            throw new ArithmeticException("element not invertible " + S);
446        }
447        return ring.getZERO();
448    }
449
450
451    /**
452     * Quotient and remainder by division of this by S.
453     * @param S a Quotient
454     * @return [this/S, this - (this/S)*S].
455     */
456    @SuppressWarnings("unchecked")
457    public Quotient<C>[] quotientRemainder(Quotient<C> S) {
458        return new Quotient[] { divide(S), remainder(S) };
459    }
460
461
462    /**
463     * Quotient multiplication.
464     * @param S Quotient.
465     * @return this*S.
466     */
467    public Quotient<C> multiply(Quotient<C> S) {
468        if (S == null || S.isZERO()) {
469            return S;
470        }
471        if (num.isZERO()) {
472            return this;
473        }
474        if (S.isONE()) {
475            return this;
476        }
477        if (this.isONE()) {
478            return S;
479        }
480        GenPolynomial<C> n;
481        if (den.isONE() && S.den.isONE()) {
482            n = num.multiply(S.num);
483            return new Quotient<C>(ring, n, den, true);
484        }
485        GenPolynomial<C> g;
486        GenPolynomial<C> d;
487        if (den.isONE()) {
488            g = ring.gcd(num, S.den);
489            n = ring.divide(num, g);
490            d = ring.divide(S.den, g);
491            n = n.multiply(S.num);
492            return new Quotient<C>(ring, n, d, true);
493        }
494        if (S.den.isONE()) {
495            g = ring.gcd(S.num, den);
496            n = ring.divide(S.num, g);
497            d = ring.divide(den, g);
498            n = n.multiply(num);
499            return new Quotient<C>(ring, n, d, true);
500        }
501        if (den.compareTo(S.den) == 0) { // correct ?
502            d = den.multiply(den);
503            n = num.multiply(S.num);
504            return new Quotient<C>(ring, n, d, true);
505        }
506        GenPolynomial<C> f;
507        GenPolynomial<C> sd;
508        GenPolynomial<C> sn;
509        g = ring.gcd(num, S.den);
510        n = ring.divide(num, g);
511        sd = ring.divide(S.den, g);
512        f = ring.gcd(den, S.num);
513        d = ring.divide(den, f);
514        sn = ring.divide(S.num, f);
515        n = n.multiply(sn);
516        d = d.multiply(sd);
517        return new Quotient<C>(ring, n, d, true);
518    }
519
520
521    /**
522     * Quotient multiplication by GenPolynomial.
523     * @param b GenPolynomial<C>.
524     * @return this*b.
525     */
526    public Quotient<C> multiply(GenPolynomial<C> b) {
527        if (b == null || b.isZERO()) {
528            return ring.getZERO();
529        }
530        if (num.isZERO()) {
531            return this;
532        }
533        if (b.isONE()) {
534            return this;
535        }
536        GenPolynomial<C> gcd = ring.gcd(b, den);
537        GenPolynomial<C> d = den;
538        if (!gcd.isONE()) {
539            b = ring.divide(b, gcd);
540            d = ring.divide(d, gcd);
541        }
542        if (this.isONE()) {
543            return new Quotient<C>(ring, b, d, true);
544        }
545        GenPolynomial<C> n = num.multiply(b);
546        return new Quotient<C>(ring, n, d, true);
547    }
548
549
550    /**
551     * Quotient multiplication by coefficient.
552     * @param b coefficient.
553     * @return this*b.
554     */
555    public Quotient<C> multiply(C b) {
556        if (b == null || b.isZERO()) {
557            return ring.getZERO();
558        }
559        if (num.isZERO()) {
560            return this;
561        }
562        if (b.isONE()) {
563            return this;
564        }
565        GenPolynomial<C> n = num.multiply(b);
566        return new Quotient<C>(ring, n, den, true);
567    }
568
569
570    /**
571     * Quotient monic.
572     * @return this with monic value part.
573     */
574    public Quotient<C> monic() {
575        if (num.isZERO()) {
576            return this;
577        }
578        C lbc = num.leadingBaseCoefficient();
579        if (!lbc.isUnit()) {
580            return this;
581        }
582        lbc = lbc.inverse();
583        //lbc = lbc.abs();
584        GenPolynomial<C> n = num.multiply(lbc);
585        //GenPolynomial<C> d = den.multiply(lbc);
586        return new Quotient<C>(ring, n, den, true);
587    }
588
589
590    /**
591     * Greatest common divisor.
592     * @param b other element.
593     * @return gcd(this,b).
594     */
595    public Quotient<C> gcd(Quotient<C> b) {
596        if (b == null || b.isZERO()) {
597            return this;
598        }
599        if (this.isZERO()) {
600            return b;
601        }
602        if (this.equals(b)) {
603            return this;
604        }
605        return ring.getONE();
606    }
607
608
609    /**
610     * Extended greatest common divisor.
611     * @param b other element.
612     * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
613     */
614    @SuppressWarnings("unchecked")
615    public Quotient<C>[] egcd(Quotient<C> b) {
616        Quotient<C>[] ret = (Quotient<C>[]) new Quotient[3];
617        ret[0] = null;
618        ret[1] = null;
619        ret[2] = null;
620        if (b == null || b.isZERO()) {
621            ret[0] = this;
622            return ret;
623        }
624        if (this.isZERO()) {
625            ret[0] = b;
626            return ret;
627        }
628        GenPolynomial<C> two = ring.ring.fromInteger(2);
629        ret[0] = ring.getONE();
630        ret[1] = (this.multiply(two)).inverse();
631        ret[2] = (b.multiply(two)).inverse();
632        return ret;
633    }
634}