001/*
002 * $Id: ResidueRing.java 3366 2010-10-24 13:02:14Z kredel $
003 */
004
005package edu.jas.poly;
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.ElemFactory;
015import edu.jas.structure.RingElem;
016import 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 */
024public 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}