001    /*
002     * $Id: LocalRing.java 3358 2010-10-23 19:27:53Z kredel $
003     */
004    
005    package edu.jas.application;
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.GcdRingElem;
015    import edu.jas.structure.RingFactory;
016    
017    import edu.jas.poly.GenPolynomial;
018    import edu.jas.poly.GenPolynomialRing;
019    
020    import edu.jas.ufd.GreatestCommonDivisor;
021    import edu.jas.ufd.GCDFactory;
022    
023    /**
024     * Local ring class based on GenPolynomial with RingElem interface.
025     * Objects of this class are effective immutable.
026     * @author Heinz Kredel
027     */
028    public class LocalRing<C extends GcdRingElem<C> > 
029                 implements RingFactory< Local<C> >  {
030    
031         private static final Logger logger = Logger.getLogger(LocalRing.class);
032         //private boolean debug = logger.isDebugEnabled();
033    
034    
035        /**
036         * Greatest common divisor engine for coefficient content and primitive parts.
037         */
038        protected final GreatestCommonDivisor<C> engine;
039    
040    
041        /** Polynomial ideal for localization. 
042         */
043        public final Ideal<C> ideal;
044    
045    
046        /** Polynomial ring of the factory. 
047         */
048        public final GenPolynomialRing<C> ring;
049    
050    
051        /** Indicator if this ring is a field.
052         */
053        protected int isField = -1; // initially unknown
054    
055    
056        /** The constructor creates a LocalRing object 
057         * from a GenPolynomialRing and a GenPolynomial. 
058         * @param i localization polynomial ideal.
059         */
060        public LocalRing(Ideal<C> i) {
061            if ( i == null ) {
062               throw new IllegalArgumentException("ideal may not be null");
063            }
064            ideal = i.GB(); // cheap if isGB
065            if ( ideal.isONE() ) {
066               throw new IllegalArgumentException("ideal may not be 1");
067            }
068            if ( !ideal.isMaximal() ) {
069                //throw new IllegalArgumentException("ideal must be maximal");
070                logger.warn("ideal not maximal");
071            }
072            ring = ideal.list.ring;
073            //engine = GCDFactory.<C>getImplementation( ring.coFac );
074            engine = GCDFactory.<C>getProxy( ring.coFac );
075        }
076    
077    
078        /**
079         * Is this structure finite or infinite.
080         * @return true if this structure is finite, else false.
081         * @see edu.jas.structure.ElemFactory#isFinite()
082         */
083        public boolean isFinite() {
084            return false;
085        }
086    
087    
088        /** Copy Local element c.
089         * @param c
090         * @return a copy of c.
091         */
092        public Local<C> copy(Local<C> c) {
093            return new Local<C>( c.ring, c.num, c.den, true );
094        }
095    
096    
097        /** Get the zero element.
098         * @return 0 as Local.
099         */
100        public Local<C> getZERO() {
101            return new Local<C>( this, ring.getZERO() );
102        }
103    
104    
105        /**  Get the one element.
106         * @return 1 as Local.
107         */
108        public Local<C> getONE() {
109            return new Local<C>( this, ring.getONE() );
110        }
111    
112    
113        /**  Get a list of the generating elements.
114         * @return list of generators for the algebraic structure.
115         * @see edu.jas.structure.ElemFactory#generators()
116         */
117        public List<Local<C>> generators() {
118            List<GenPolynomial<C>> pgens = ring.generators();
119            List<Local<C>> gens = new ArrayList<Local<C>>( pgens.size() );
120            for ( GenPolynomial<C> p : pgens ) {
121                Local<C> q = new Local<C>( this, p );
122                gens.add(q);
123            }
124            return gens;
125        }
126    
127        
128        /**
129         * Query if this ring is commutative.
130         * @return true if this ring is commutative, else false.
131         */
132        public boolean isCommutative() {
133            return ring.isCommutative();
134        }
135    
136    
137        /**
138         * Query if this ring is associative.
139         * @return true if this ring is associative, else false.
140         */
141        public boolean isAssociative() {
142            return ring.isAssociative();
143        }
144    
145    
146        /**
147         * Query if this ring is a field.
148         * @return false.
149         */
150        public boolean isField() {
151            if ( isField > 0 ) { 
152               return true;
153            }
154            if ( isField == 0 ) { 
155               return false;
156            }
157            // ??
158            return false;
159        }
160    
161    
162        /**
163         * Characteristic of this ring.
164         * @return characteristic of this ring.
165         */
166        public java.math.BigInteger characteristic() {
167            return ring.characteristic();
168        }
169    
170    
171        /** Get a Local element from a BigInteger value.
172         * @param a BigInteger.
173         * @return a Local.
174         */
175        public Local<C> fromInteger(java.math.BigInteger a) {
176            return new Local<C>( this, ring.fromInteger(a) );
177        }
178    
179    
180        /** Get a Local element from a long value.
181         * @param a long.
182         * @return a Local.
183         */
184        public Local<C> fromInteger(long a) {
185            return new Local<C>( this, ring.fromInteger(a) );
186        }
187        
188    
189        /** Get the String representation as RingFactory.
190         * @see java.lang.Object#toString()
191         */
192        @Override
193         public String toString() {
194            return "Local[ " 
195                    + ideal.toString() + " ]";
196        }
197    
198    
199        /** Get a scripting compatible string representation.
200         * @return script compatible representation for this ElemFactory.
201         * @see edu.jas.structure.ElemFactory#toScript()
202         */
203        //JAVA6only: @Override
204        public String toScript() {
205            // Python case
206            return "LC(" + ideal.list.toScript() + ")";
207        }
208    
209    
210        /** Comparison with any other object.
211         * @see java.lang.Object#equals(java.lang.Object)
212         */
213        @Override
214        @SuppressWarnings("unchecked") // not jet working
215        public boolean equals(Object b) {
216            if ( ! ( b instanceof LocalRing ) ) {
217               return false;
218            }
219            LocalRing<C> a = null;
220            try {
221                a = (LocalRing<C>) b;
222            } catch (ClassCastException e) {
223            }
224            if ( a == null ) {
225                return false;
226            }
227            if ( ! ring.equals( a.ring ) ) {
228                return false;
229            }
230            return ideal.equals( a.ideal );
231        }
232    
233    
234        /** Hash code for this local ring.
235         * @see java.lang.Object#hashCode()
236         */
237        @Override
238        public int hashCode() { 
239           int h;
240           h = ideal.hashCode();
241           return h;
242        }
243    
244    
245        /** Local random.
246         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
247         * @return a random residue element.
248         */
249        public Local<C> random(int n) {
250          GenPolynomial<C> r = ring.random( n ).monic();
251          GenPolynomial<C> s = ring.random( n ).monic();
252          s = ideal.normalform( s );
253          while ( s.isZERO() ) {
254              logger.info("s was in ideal");
255              s = ring.random( n ).monic();
256              s = ideal.normalform( s );
257          }
258          return new Local<C>( this, r, s, false );
259        }
260    
261    
262        /**
263         * Generate a random residum polynomial.
264         * @param k bitsize of random coefficients.
265         * @param l number of terms.
266         * @param d maximal degree in each variable.
267         * @param q density of nozero exponents.
268         * @return a random residue polynomial.
269         */
270        public Local<C> random(int k, int l, int d, float q) {
271          GenPolynomial<C> r = ring.random(k,l,d,q).monic();
272          GenPolynomial<C> s = ring.random(k,l,d,q).monic();
273          s = ideal.normalform( s );
274          while ( s.isZERO() ) {
275              logger.info("s was in ideal "+ideal);
276              s = ring.random( k,l,d,q ).monic();
277              s = ideal.normalform( s );
278          }
279          return new Local<C>( this, r, s, false );
280        }
281    
282    
283        /** Local random.
284         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
285         * @param rnd is a source for random bits.
286         * @return a random residue element.
287         */
288        public Local<C> random(int n, Random rnd) {
289          GenPolynomial<C> r = ring.random( n, rnd ).monic();
290          GenPolynomial<C> s = ring.random( n, rnd ).monic();
291          s = ideal.normalform( s );
292          while ( s.isZERO() ) {
293              logger.info("s was in ideal");
294              s = ring.random( n, rnd ).monic();
295              s = ideal.normalform( s );
296          }
297          return new Local<C>( this, r, s, false);
298        }
299    
300    
301        /** Parse Local from String.
302         * @param s String.
303         * @return Local from s.
304         */
305        public Local<C> parse(String s) {
306            GenPolynomial<C> x = ring.parse( s );
307            return new Local<C>( this, x );
308        }
309    
310    
311        /** Parse Local from Reader.
312         * @param r Reader.
313         * @return next Local from r.
314         */
315        public Local<C> parse(Reader r) {
316            GenPolynomial<C> x = ring.parse( r );
317            return new Local<C>( this, x );
318        }
319    
320    }