001    /*
002     * $Id: Residue.java 3287 2010-08-23 21:29:53Z kredel $
003     */
004    
005    package edu.jas.application;
006    
007    import edu.jas.poly.GenPolynomial;
008    import edu.jas.poly.PolyUtil;
009    
010    import edu.jas.kern.PrettyPrint;
011    
012    import edu.jas.structure.GcdRingElem;
013    import edu.jas.structure.RingFactory;
014    
015    
016    /**
017     * Residue ring element based on GenPolynomial with RingElem interface.
018     * Objects of this class are (nearly) immutable.
019     * @author Heinz Kredel
020     */
021    public class Residue<C extends GcdRingElem<C> > 
022                 implements GcdRingElem< Residue<C> > {
023    
024    
025        /** Residue class factory data structure. 
026         */
027        public final ResidueRing<C> ring;
028    
029    
030        /** Value part of the element data structure. 
031         */
032        public final GenPolynomial<C> val;
033    
034    
035        /** Flag to remember if this residue element is a unit.
036         * -1 is unknown, 1 is unit, 0 not a unit.
037         */
038        protected int isunit = -1; // initially unknown
039    
040    
041        /** The constructor creates a Residue object 
042         * from a ring factory. 
043         * @param r ring factory.
044         */
045        public Residue(ResidueRing<C> r) {
046            this( r, r.ring.getZERO(), 0 );
047        }
048    
049    
050        /** The constructor creates a Residue object 
051         * from a ring factory and a polynomial. 
052         * @param r ring factory.
053         * @param a polynomial list.
054         */
055        public Residue(ResidueRing<C> r, GenPolynomial<C> a) {
056            this( r, a, -1 );
057        }
058    
059    
060        /** The constructor creates a Residue object 
061         * from a ring factory, a polynomial and an indicator if a is a unit. 
062         * @param r ring factory.
063         * @param a polynomial list.
064         * @param u isunit indicator, -1, 0, 1.
065         */
066        public Residue(ResidueRing<C> r, GenPolynomial<C> a, int u) {
067            ring = r;
068            val = ring.ideal.normalform( a ); //.monic() no go
069            switch ( u ) {
070            case 0:  isunit = u;
071                     break;
072            case 1:  isunit = u;
073                     break;
074            default: isunit = -1;
075            }
076            if ( val.isONE() ) {
077               isunit = 1;
078            }
079            if ( val.isZERO() ) {
080               isunit = 0;
081            }
082        }
083    
084        /**
085         * Get the corresponding element factory.
086         * @return factory for this Element.
087         * @see edu.jas.structure.Element#factory()
088         */
089        public ResidueRing<C> factory() {
090            return ring;
091        }
092    
093    
094        /**  Clone this.
095         * @see java.lang.Object#clone()
096         */
097        @Override
098        public Residue<C> clone() {
099            return new Residue<C>( ring, val, isunit );
100        }
101       
102    
103        /** Is Residue zero. 
104         * @return If this is 0 then true is returned, else false.
105         * @see edu.jas.structure.RingElem#isZERO()
106         */
107        public boolean isZERO() {
108            // ??return val.equals( ring.ring.getZERO() );
109            return val.isZERO();
110        }
111    
112    
113        /** Is Residue one. 
114         * @return If this is 1 then true is returned, else false.
115         * @see edu.jas.structure.RingElem#isONE()
116         */
117        public boolean isONE() {
118            // ?? return val.equals( ring.ring.getONE() );
119            return val.isONE();
120        }
121    
122    
123        /** Is Residue unit. 
124         * @return If this is a unit then true is returned, else false.
125         * @see edu.jas.structure.RingElem#isUnit()
126         */
127        public boolean isUnit() {
128            if ( isunit > 0 ) {
129                return true;
130            } 
131            if ( isunit == 0 ) {
132                return false;
133            } 
134            // not jet known
135            boolean u = ring.ideal.isUnit( val );
136            if ( u ) {
137               isunit = 1;
138            } else {
139               isunit = 0;
140            }
141            return ( u );
142        }
143    
144    
145        /** Is Residue a constant. 
146         * @return true if this.val is a constant polynomial, else false.
147         */
148        public boolean isConstant() {
149            return val.isConstant();
150        }
151    
152    
153        /** Get the String representation as RingElem.
154         * @see java.lang.Object#toString()
155         */
156        @Override
157        public String toString() {
158            if ( PrettyPrint.isTrue() ) {
159               return val.toString( ring.ring.getVars() );
160            } else {
161               return "Residue[ " + val.toString() 
162                       + " mod " + ring.toString() + " ]";
163            }
164        }
165    
166    
167        /** Get a scripting compatible string representation.
168         * @return script compatible representation for this Element.
169         * @see edu.jas.structure.Element#toScript()
170         */
171        //JAVA6only: @Override
172        public String toScript() {
173            // Python case
174            return val.toScript(); 
175    //         return "PolyResidue( " + val.toScript() 
176    //                         + ", " + ring.toScript() + " )";
177        }
178    
179    
180        /** Get a scripting compatible string representation of the factory.
181         * @return script compatible representation for this ElemFactory.
182         * @see edu.jas.structure.Element#toScriptFactory()
183         */
184        //JAVA6only: @Override
185        public String toScriptFactory() {
186            // Python case
187            return factory().toScript();
188        }
189    
190    
191        /** Residue comparison.  
192         * @param b Residue.
193         * @return sign(this-b), 0 means that this and b are equivalent in this residue class ring.
194         */
195        //JAVA6only: @Override
196        public int compareTo(Residue<C> b) {
197            GenPolynomial<C> v = b.val;
198            if ( ! ring.equals( b.ring ) ) {
199               v = ring.ideal.normalform( v );
200            }
201            return val.compareTo( v );
202        }
203    
204    
205        /** Comparison with any other object.
206         * @see java.lang.Object#equals(java.lang.Object)
207         * @return true means that this and b are equivalent in this residue class ring.
208         */
209        @Override
210        @SuppressWarnings("unchecked") 
211        public boolean equals(Object b) {
212            if ( ! ( b instanceof Residue ) ) {
213               return false;
214            }
215            Residue<C> a = null;
216            try {
217                a = (Residue<C>) b;
218            } catch (ClassCastException e) {
219            }
220            if ( a == null ) {
221                return false;
222            }
223            return ( 0 == compareTo( a ) );
224        }
225    
226    
227        /** Hash code for this local.
228         * @see java.lang.Object#hashCode()
229         */
230        @Override
231        public int hashCode() { 
232           int h;
233           h = ring.hashCode();
234           h = 37 * h + val.hashCode();
235           return h;
236        }
237    
238    
239        /** Residue absolute value.
240         * @return the absolute value of this.
241         * @see edu.jas.structure.RingElem#abs()
242         */
243        public Residue<C> abs() {
244            return new Residue<C>( ring, val.abs(), isunit );
245        }
246    
247    
248        /** Residue summation.
249         * @param S Residue.
250         * @return this+S.
251         */
252        public Residue<C> sum(Residue<C> S) {
253            return new Residue<C>( ring, val.sum( S.val ) );
254        }
255    
256    
257        /** Residue negate.
258         * @return -this.
259         * @see edu.jas.structure.RingElem#negate()
260         */
261        public Residue<C> negate() {
262            return new Residue<C>( ring, val.negate(), isunit );
263        }
264    
265    
266        /** Residue signum.
267         * @see edu.jas.structure.RingElem#signum()
268         * @return signum(this).
269         */
270        public int signum() {
271            return val.signum();
272        }
273    
274    
275        /** Residue subtraction.
276         * @param S Residue.
277         * @return this-S.
278         */
279        public Residue<C> subtract(Residue<C> S) {
280            return new Residue<C>( ring, val.subtract( S.val ) );
281        }
282    
283    
284        /** Residue division.
285         * @param S Residue.
286         * @return this/S.
287         */
288        public Residue<C> divide(Residue<C> S) {
289            if ( ring.isField() ) {
290                return multiply( S.inverse() );
291            }
292            GenPolynomial<C> x = PolyUtil.<C>basePseudoDivide( val, S.val );
293            return new Residue<C>( ring, x );
294        }
295    
296    
297        /** Residue inverse.  
298         * @see edu.jas.structure.RingElem#inverse()
299         * @return S with S = 1/this if defined. 
300         */
301        public Residue<C> inverse() {
302            GenPolynomial<C> x = ring.ideal.inverse( val );
303            return new Residue<C>( ring, x, 1 );
304        }
305    
306    
307        /** Residue remainder.
308         * @param S Residue.
309         * @return this - (this/S)*S.
310         */
311        public Residue<C> remainder(Residue<C> S) {
312            //GenPolynomial<C> x = val.remainder( S.val );
313            GenPolynomial<C> x = PolyUtil.<C>basePseudoRemainder( val, S.val );
314            return new Residue<C>( ring, x );
315        }
316    
317    
318        /** Residue multiplication.
319         * @param S Residue.
320         * @return this*S.
321         */
322        public Residue<C> multiply(Residue<C> S) {
323            GenPolynomial<C> x = val.multiply( S.val );
324            int i = -1;
325            if ( isunit == 1 && S.isunit == 1 ) {
326               i = 1;
327            } else if ( isunit == 0 || S.isunit == 0 ) {
328               i = 0;
329            }
330            return new Residue<C>( ring, x, i );
331        }
332    
333     
334        /** Residue monic.
335         * @return this with monic value part.
336         */
337        public Residue<C> monic() {
338            return new Residue<C>( ring, val.monic(), isunit );
339        }
340    
341    
342        /**
343         * Greatest common divisor.
344         * @param b other element.
345         * @return gcd(this,b).
346         */
347        public Residue<C> gcd(Residue<C> b) {
348            GenPolynomial<C> x = ring.engine.gcd( val, b.val );
349            int i = -1; // gcd might become a unit
350            if ( x.isONE() ) {
351                i = 1;
352            } else {
353               System.out.println("Residue gcd = " + x);
354            }
355            if ( isunit == 1 && b.isunit == 1 ) {
356               i = 1;
357            }
358            return new Residue<C>( ring, x, i );
359        }
360    
361    
362        /**
363         * Extended greatest common divisor.
364         * <b>Note: </b>Not implemented, throws UnsupportedOperationException.
365         * @param b other element.
366         * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
367         */
368        public Residue<C>[] egcd(Residue<C> b) {
369            throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName());
370        }
371    }