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