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