001    /*
002     * $Id: ResidueRing.java 3366 2010-10-24 13:02:14Z kredel $
003     */
004    
005    package edu.jas.poly;
006    
007    import java.util.Random;
008    import java.util.List;
009    import java.util.ArrayList;
010    import java.io.Reader;
011    
012    import org.apache.log4j.Logger;
013    
014    import edu.jas.structure.ElemFactory;
015    import edu.jas.structure.RingElem;
016    import edu.jas.structure.RingFactory;
017    
018    
019    /**
020     * Residue ring factory based on RingElem and RingFactory module.
021     * Objects of this class are immutable.
022     * @author Heinz Kredel
023     */
024    public class ResidueRing<C extends RingElem<C> > 
025                 implements RingFactory< Residue<C> >  {
026    
027        private static final Logger logger = Logger.getLogger(ResidueRing.class);
028        //private boolean debug = logger.isDebugEnabled();
029    
030    
031        /** Ring element for reduction. 
032         */
033        protected final C modul;
034    
035    
036        /** Ring factory. 
037         */
038        protected final RingFactory<C> ring;
039    
040    
041        /** Indicator if this ring is a field.
042         */
043        protected int isField = -1; // initially unknown
044    
045    
046        /** The constructor creates a ResidueRing object 
047         * from an ring factory and a modul. 
048         * @param r ring factory.
049         * @param m modul.
050         */
051        public ResidueRing(RingFactory<C> r, C m) {
052            ring = r;
053            if ( m.isZERO() ) {
054               throw new IllegalArgumentException("modul may not be null");
055            }
056            if ( m.isONE() ) {
057               logger.warn("modul is one");
058            }
059            if ( m.signum() < 0 ) {
060               m = m.negate();
061            }
062            modul = m; 
063        }
064    
065    
066        /**
067         * Is this structure finite or infinite.
068         * @return true if this structure is finite, else false.
069         * @see edu.jas.structure.ElemFactory#isFinite()
070         */
071        public boolean isFinite() {
072            throw new UnsupportedOperationException("not implemented");
073            //return ring.isFinite();
074        }
075    
076    
077        /** Copy Residue element c.
078         * @param c
079         * @return a copy of c.
080         */
081        public Residue<C> copy(Residue<C> c) {
082            return new Residue<C>( c.ring, c.val );
083        }
084    
085    
086        /** Get the zero element.
087         * @return 0 as Residue.
088         */
089        public Residue<C> getZERO() {
090            return new Residue<C>( this, ring.getZERO() );
091        }
092    
093    
094        /**  Get the one element.
095         * @return 1 as Residue.
096         */
097        public Residue<C> getONE() {
098            Residue<C> one = new Residue<C>( this, ring.getONE() );
099            if ( one.isZERO() ) {
100               logger.warn("one is zero, so all residues are 0");
101            }
102            return one;
103        }
104    
105    
106        /**  Get a list of the generating elements.
107         * @return list of generators for the algebraic structure.
108         * @see edu.jas.structure.ElemFactory#generators()
109         */
110        public List<Residue<C>> generators() {
111            List<? extends C> rgens = ring.generators();
112            List<Residue<C>> gens = new ArrayList<Residue<C> >( rgens.size() );
113            for ( C c: rgens ) {
114                 gens.add( new Residue<C>(this,c) );
115            }
116            return gens;
117        }
118    
119        
120        /**
121         * Query if this ring is commutative.
122         * @return true if this ring is commutative, else false.
123         */
124        public boolean isCommutative() {
125            return ring.isCommutative();
126        }
127    
128    
129        /**
130         * Query if this ring is associative.
131         * @return true if this ring is associative, else false.
132         */
133        public boolean isAssociative() {
134            return ring.isAssociative();
135        }
136    
137    
138        /**
139         * Query if this ring is a field.
140         * @return false.
141         */
142        public boolean isField() {
143            if ( isField > 0 ) { 
144               return true;
145            }
146            if ( isField == 0 ) { 
147               return false;
148            }
149            // ideal is prime ?
150            return false;
151        }
152    
153    
154        /**
155         * Characteristic of this ring.
156         * @return characteristic of this ring.
157         */
158        public java.math.BigInteger characteristic() {
159            return ring.characteristic();
160        }
161    
162    
163        /** Get a Residue element from a BigInteger value.
164         * @param a BigInteger.
165         * @return a Residue.
166         */
167        public Residue<C> fromInteger(java.math.BigInteger a) {
168            return new Residue<C>( this, ring.fromInteger(a) );
169        }
170    
171    
172        /** Get a Residue element from a long value.
173         * @param a long.
174         * @return a Residue.
175         */
176        public Residue<C> fromInteger(long a) {
177            return new Residue<C>( this, ring.fromInteger(a) );
178        }
179        
180    
181        /** Get the String representation as RingFactory.
182         * @see java.lang.Object#toString()
183         */
184        @Override
185         public String toString() {
186            return "Residue[ " 
187                    + modul.toString() + " ]";
188        }
189    
190    
191        /** Get a scripting compatible string representation.
192         * @return script compatible representation for this ElemFactory.
193         * @see edu.jas.structure.ElemFactory#toScript()
194         */
195        //JAVA6only: @Override
196        public String toScript() {
197            // Python case
198            return "ResidueRing(" + modul.toScript() + ")";
199        }
200    
201    
202        /** Comparison with any other object.
203         * @see java.lang.Object#equals(java.lang.Object)
204         */
205        @Override
206        @SuppressWarnings("unchecked") // not jet working
207        public boolean equals(Object b) {
208            if ( ! ( b instanceof ResidueRing ) ) {
209               return false;
210            }
211            ResidueRing<C> a = null;
212            try {
213                a = (ResidueRing<C>) b;
214            } catch (ClassCastException e) {
215            }
216            if ( a == null ) {
217                return false;
218            }
219            if ( ! ring.equals( a.ring ) ) {
220                return false;
221            }
222            return modul.equals( a.modul );
223        }
224    
225    
226        /** Hash code for this residue ring.
227         * @see java.lang.Object#hashCode()
228         */
229        @Override
230        public int hashCode() { 
231           int h;
232           h = ring.hashCode();
233           h = 37 * h + modul.hashCode();
234           return h;
235        }
236    
237    
238        /** Residue random.
239         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
240         * @return a random residue element.
241         */
242        public Residue<C> random(int n) {
243          C x = ring.random( n );
244          // x = x.sum( ring.getONE() );
245          return new Residue<C>( this, x );
246        }
247    
248    
249        /** Residue random.
250         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
251         * @param rnd is a source for random bits.
252         * @return a random residue element.
253         */
254        public Residue<C> random(int n, Random rnd) {
255          C x = ring.random( n, rnd );
256          // x = x.sum( ring.getONE() );
257          return new Residue<C>( this, x);
258        }
259    
260    
261        /** Parse Residue from String.
262         * @param s String.
263         * @return Residue from s.
264         */
265        public Residue<C> parse(String s) {
266            C x = ring.parse( s );
267            return new Residue<C>( this, x );
268        }
269    
270    
271        /** Parse Residue from Reader.
272         * @param r Reader.
273         * @return next Residue from r.
274         */
275        public Residue<C> parse(Reader r) {
276            C x = ring.parse( r );
277            return new Residue<C>( this, x );
278        }
279    
280    }