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