001/*
002 * $Id: LocalRing.java 3358 2010-10-23 19:27:53Z kredel $
003 */
004
005package edu.jas.application;
006
007import java.util.Random;
008import java.util.List;
009import java.util.ArrayList;
010import java.io.Reader;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.structure.GcdRingElem;
015import edu.jas.structure.RingFactory;
016
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019
020import edu.jas.ufd.GreatestCommonDivisor;
021import 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 */
028public 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}