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