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