001/*
002 * $Id: Quotient.java 4957 2014-10-16 23:03:23Z kredel $
003 */
004
005package edu.jas.poly;
006
007
008import org.apache.log4j.Logger;
009
010import edu.jas.structure.GcdRingElem;
011import edu.jas.structure.QuotPair;
012import edu.jas.structure.RingElem;
013
014
015/**
016 * Quotient element based on RingElem pairs. Objects of this class are
017 * immutable.
018 * @author Heinz Kredel
019 */
020public class Quotient<C extends RingElem<C>> implements RingElem<Quotient<C>>, QuotPair<C> {
021
022
023    private static final Logger logger = Logger.getLogger(Quotient.class);
024
025
026    private final boolean debug = logger.isDebugEnabled();
027
028
029    /**
030     * Quotient class factory data structure.
031     */
032    public final QuotientRing<C> ring;
033
034
035    /**
036     * Numerator part of the element data structure.
037     */
038    public final C num;
039
040
041    /**
042     * Denominator part of the element data structure.
043     */
044    public final C den;
045
046
047    /**
048     * The constructor creates a Quotient object from a ring factory.
049     * @param r ring factory.
050     */
051    public Quotient(QuotientRing<C> r) {
052        this(r, r.ring.getZERO());
053    }
054
055
056    /**
057     * The constructor creates a Quotient object from a ring factory and a
058     * numerator element. The denominator is assumed to be 1.
059     * @param r ring factory.
060     * @param n numerator.
061     */
062    public Quotient(QuotientRing<C> r, C n) {
063        this(r, n, r.ring.getONE(), true);
064    }
065
066
067    /**
068     * The constructor creates a Quotient object from a ring factory and a
069     * numerator and denominator element.
070     * @param r ring factory.
071     * @param n numerator.
072     * @param d denominator.
073     */
074    public Quotient(QuotientRing<C> r, C n, C d) {
075        this(r, n, d, false);
076    }
077
078
079    /**
080     * The constructor creates a Quotient object from a ring factory and a
081     * numerator and denominator element.
082     * @param r ring factory.
083     * @param n numerator.
084     * @param d denominator.
085     * @param isred true if gcd(n,d) == 1, else false.
086     */
087    @SuppressWarnings("unchecked")
088    protected Quotient(QuotientRing<C> r, C n, C d, boolean isred) {
089        if (d == null || d.isZERO()) {
090            throw new IllegalArgumentException("denominator may not be zero");
091        }
092        ring = r;
093        if (d.signum() < 0) {
094            n = n.negate();
095            d = d.negate();
096        }
097        if (isred) {
098            num = n;
099            den = d;
100            return;
101        }
102        // must reduce to lowest terms
103        if (n instanceof GcdRingElem && d instanceof GcdRingElem) {
104            GcdRingElem ng = (GcdRingElem) n;
105            GcdRingElem dg = (GcdRingElem) d;
106            C gcd = (C) ng.gcd(dg);
107            if (debug) {
108                logger.info("gcd = " + gcd);
109            }
110            //RingElem<C> gcd = ring.ring.getONE();
111            if (gcd.isONE()) {
112                num = n;
113                den = d;
114            } else {
115                num = n.divide(gcd);
116                den = d.divide(gcd);
117            }
118            // } else { // univariate polynomial?
119        } else {
120            logger.warn("gcd = ????");
121            num = n;
122            den = d;
123        }
124    }
125
126
127    /**
128     * Get the corresponding element factory.
129     * @return factory for this Element.
130     * @see edu.jas.structure.Element#factory()
131     */
132    public QuotientRing<C> factory() {
133        return ring;
134    }
135
136
137    /**
138     * Numerator.
139     * @see edu.jas.structure.QuotPair#numerator()
140     */
141    public C numerator() {
142        return num;
143    }
144
145
146    /**
147     * Denominator.
148     * @see edu.jas.structure.QuotPair#denominator()
149     */
150    public C denominator() {
151        return den;
152    }
153
154
155    /**
156     * Is Quotient a constant. Not implemented.
157     * @throws UnsupportedOperationException.
158     */
159    public boolean isConstant() {
160        throw new UnsupportedOperationException("isConstant not implemented");
161    }
162
163
164    /**
165     * Clone this.
166     * @see java.lang.Object#clone()
167     */
168    @Override
169    public Quotient<C> copy() {
170        return new Quotient<C>(ring, num, den, true);
171    }
172
173
174    /**
175     * Is Quotient zero.
176     * @return If this is 0 then true is returned, else false.
177     * @see edu.jas.structure.RingElem#isZERO()
178     */
179    public boolean isZERO() {
180        return num.isZERO();
181    }
182
183
184    /**
185     * Is Quotient one.
186     * @return If this is 1 then true is returned, else false.
187     * @see edu.jas.structure.RingElem#isONE()
188     */
189    public boolean isONE() {
190        return num.equals(den);
191    }
192
193
194    /**
195     * Is Quotient unit.
196     * @return If this is a unit then true is returned, else false.
197     * @see edu.jas.structure.RingElem#isUnit()
198     */
199    public boolean isUnit() {
200        if (num.isZERO()) {
201            return false;
202        }
203        return true;
204    }
205
206
207    /**
208     * Get the String representation as RingElem.
209     * @see java.lang.Object#toString()
210     */
211    @Override
212    public String toString() {
213        return "Quotient[ " + num.toString() + " / " + den.toString() + " ]";
214    }
215
216
217    /**
218     * Get a scripting compatible string representation.
219     * @return script compatible representation for this Element.
220     * @see edu.jas.structure.Element#toScript()
221     */
222    @Override
223    public String toScript() {
224        // Python case
225        return "Quotient( " + num.toScript() + " , " + den.toScript() + " )";
226    }
227
228
229    /**
230     * Get a scripting compatible string representation of the factory.
231     * @return script compatible representation for this ElemFactory.
232     * @see edu.jas.structure.Element#toScriptFactory()
233     */
234    @Override
235    public String toScriptFactory() {
236        // Python case
237        return factory().toScript();
238    }
239
240
241    /**
242     * Quotient comparison.
243     * @param b Quotient.
244     * @return sign(this-b).
245     */
246    @Override
247    public int compareTo(Quotient<C> b) {
248        if (b == null || b.isZERO()) {
249            return this.signum();
250        }
251        C r = num.multiply(b.den);
252        C s = den.multiply(b.num);
253        C x = r.subtract(s);
254        return x.signum();
255    }
256
257
258    /**
259     * Comparison with any other object.
260     * @see java.lang.Object#equals(java.lang.Object)
261     */
262    @Override
263    @SuppressWarnings("unchecked")
264    public boolean equals(Object b) {
265        if (b == null) {
266            return false;
267        }
268        if (!(b instanceof Quotient)) {
269            return false;
270        }
271        Quotient<C> a = (Quotient<C>) b;
272        return (0 == compareTo(a));
273    }
274
275
276    /**
277     * Hash code for this local.
278     * @see java.lang.Object#hashCode()
279     */
280    @Override
281    public int hashCode() {
282        int h;
283        h = ring.hashCode();
284        h = 37 * h + num.hashCode();
285        h = 37 * h + den.hashCode();
286        return h;
287    }
288
289
290    /**
291     * Quotient absolute value.
292     * @return the absolute value of this.
293     * @see edu.jas.structure.RingElem#abs()
294     */
295    public Quotient<C> abs() {
296        return new Quotient<C>(ring, num.abs(), den, true);
297    }
298
299
300    /**
301     * Quotient summation.
302     * @param S Quotient.
303     * @return this+S.
304     */
305    public Quotient<C> sum(Quotient<C> S) {
306        if (S == null || S.isZERO()) {
307            return this;
308        }
309        C n = num.multiply(S.den);
310        n = n.sum(den.multiply(S.num));
311        C d = den.multiply(S.den);
312        return new Quotient<C>(ring, n, d, false);
313    }
314
315
316    /**
317     * Quotient negate.
318     * @return -this.
319     * @see edu.jas.structure.RingElem#negate()
320     */
321    public Quotient<C> negate() {
322        return new Quotient<C>(ring, num.negate(), den, true);
323    }
324
325
326    /**
327     * Quotient signum.
328     * @see edu.jas.structure.RingElem#signum()
329     * @return signum(this).
330     */
331    public int signum() {
332        return num.signum();
333    }
334
335
336    /**
337     * Quotient subtraction.
338     * @param S Quotient.
339     * @return this-S.
340     */
341    public Quotient<C> subtract(Quotient<C> S) {
342        if (S == null || S.isZERO()) {
343            return this;
344        }
345        C n = num.multiply(S.den);
346        n = n.subtract(den.multiply(S.num));
347        C d = den.multiply(S.den);
348        return new Quotient<C>(ring, n, d, false);
349    }
350
351
352    /**
353     * Quotient division.
354     * @param S Quotient.
355     * @return this/S.
356     */
357    public Quotient<C> divide(Quotient<C> S) {
358        return multiply(S.inverse());
359    }
360
361
362    /**
363     * Quotient inverse.
364     * @see edu.jas.structure.RingElem#inverse()
365     * @return S with S = 1/this.
366     */
367    public Quotient<C> inverse() {
368        return new Quotient<C>(ring, den, num, true);
369    }
370
371
372    /**
373     * Quotient remainder.
374     * @param S Quotient.
375     * @return this - (this/S)*S.
376     */
377    public Quotient<C> remainder(Quotient<C> S) {
378        if (num.isZERO()) {
379            throw new ArithmeticException("element not invertible " + this);
380        }
381        return ring.getZERO();
382    }
383
384
385    /**
386     * Quotient and remainder by division of this by S.
387     * @param S a Quotient
388     * @return [this/S, this - (this/S)*S].
389     */
390    public Quotient<C>[] quotientRemainder(Quotient<C> S) {
391        return new Quotient[] { divide(S), remainder(S) };
392    }
393
394
395    /**
396     * Quotient multiplication.
397     * @param S Quotient.
398     * @return this*S.
399     */
400    public Quotient<C> multiply(Quotient<C> S) {
401        if (S == null || S.isZERO()) {
402            return S;
403        }
404        if (num.isZERO()) {
405            return this;
406        }
407        if (S.isONE()) {
408            return this;
409        }
410        if (this.isONE()) {
411            return S;
412        }
413        C n = num.multiply(S.num);
414        C d = den.multiply(S.den);
415        return new Quotient<C>(ring, n, d, false);
416    }
417
418
419    /**
420     * Quotient monic.
421     * @return this with monic value part.
422     */
423    public Quotient<C> monic() {
424        logger.info("monic not implemented");
425        return this;
426    }
427
428
429    /**
430     * Greatest common divisor. <b>Note:</b> If not defined, throws
431     * UnsupportedOperationException.
432     * @param b other element.
433     * @return gcd(this,b).
434     */
435    public Quotient<C> gcd(Quotient<C> b) {
436        if (b == null || b.isZERO()) {
437            return this;
438        }
439        if (this.isZERO()) {
440            return b;
441        }
442        if (num instanceof GcdRingElem && den instanceof GcdRingElem && b.num instanceof GcdRingElem
443                        && b.den instanceof GcdRingElem) {
444            return ring.getONE();
445        }
446        throw new UnsupportedOperationException("gcd not implemented " + num.getClass().getName());
447    }
448
449
450    /**
451     * Extended greatest common divisor. <b>Note:</b> If not defined, throws
452     * UnsupportedOperationException.
453     * @param b other element.
454     * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
455     */
456    public Quotient<C>[] egcd(Quotient<C> b) {
457        @SuppressWarnings("cast")
458        Quotient<C>[] ret = (Quotient<C>[]) new Quotient[3];
459        ret[0] = null;
460        ret[1] = null;
461        ret[2] = null;
462        if (b == null || b.isZERO()) {
463            ret[0] = this;
464            return ret;
465        }
466        if (this.isZERO()) {
467            ret[0] = b;
468            return ret;
469        }
470        if (num instanceof GcdRingElem && den instanceof GcdRingElem && b.num instanceof GcdRingElem
471                        && b.den instanceof GcdRingElem) {
472            Quotient<C> two = ring.fromInteger(2);
473            ret[0] = ring.getONE();
474            ret[1] = (this.multiply(two)).inverse();
475            ret[2] = (b.multiply(two)).inverse();
476            return ret;
477        }
478        throw new UnsupportedOperationException("egcd not implemented " + num.getClass().getName());
479    }
480
481}