001/*
002 * $Id: LocalRing.java 3367 2010-10-24 13:05:02Z kredel $
003 */
004
005package edu.jas.poly;
006
007import java.util.Random;
008import java.io.Reader;
009import java.util.List;
010import java.util.ArrayList;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.structure.ElemFactory;
015import edu.jas.structure.RingElem;
016import 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 */
024public 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}