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