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