001/*
002 * $Id: LocalRing.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.QuotPairFactory;
016import edu.jas.structure.RingElem;
017import edu.jas.structure.RingFactory;
018
019
020/**
021 * Local ring factory based on RingElem principal ideal. Objects of this class
022 * are immutable.
023 * @author Heinz Kredel
024 */
025public class LocalRing<C extends RingElem<C>> implements RingFactory<Local<C>>, QuotPairFactory<C, Local<C>> {
026
027
028    private static final Logger logger = Logger.getLogger(LocalRing.class);
029
030
031    //private boolean debug = logger.isDebugEnabled();
032
033
034    /**
035     * Ideal generator for localization.
036     */
037    protected final C ideal;
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 LocalRing object from a RingFactory and a
054     * RingElem.
055     * @param i localization ideal generator.
056     */
057    public LocalRing(RingFactory<C> r, C i) {
058        ring = r;
059        if (i == null) {
060            throw new IllegalArgumentException("ideal may not be null");
061        }
062        ideal = i;
063        if (ideal.isONE()) {
064            throw new IllegalArgumentException("ideal may not be 1");
065        }
066    }
067
068
069    /**
070     * Factory for base elements.
071     */
072    public RingFactory<C> pairFactory() {
073        return ring;
074    }
075
076
077    /**
078     * Create from numerator.
079     */
080    public Local<C> create(C n) {
081        return new Local<C>(this, n);
082    }
083
084
085    /**
086     * Create from numerator, denominator pair.
087     */
088    public Local<C> create(C n, C d) {
089        return new Local<C>(this, n, d);
090    }
091
092
093    /**
094     * Is this structure finite or infinite.
095     * @return true if this structure is finite, else false.
096     * @see edu.jas.structure.ElemFactory#isFinite()
097     */
098    public boolean isFinite() {
099        return ring.isFinite();
100    }
101
102
103    /**
104     * Copy Local element c.
105     * @param c
106     * @return a copy of c.
107     */
108    public Local<C> copy(Local<C> c) {
109        return new Local<C>(c.ring, c.num, c.den, true);
110    }
111
112
113    /**
114     * Get the zero element.
115     * @return 0 as Local.
116     */
117    public Local<C> getZERO() {
118        return new Local<C>(this, ring.getZERO());
119    }
120
121
122    /**
123     * Get the one element.
124     * @return 1 as Local.
125     */
126    public Local<C> getONE() {
127        return new Local<C>(this, ring.getONE());
128    }
129
130
131    /**
132     * Get a list of the generating elements.
133     * @return list of generators for the algebraic structure.
134     * @see edu.jas.structure.ElemFactory#generators()
135     */
136    public List<Local<C>> generators() {
137        List<? extends C> rgens = ring.generators();
138        List<Local<C>> gens = new ArrayList<Local<C>>(rgens.size() - 1);
139        for (C c : rgens) {
140            if (!c.isONE()) {
141                gens.add(new Local<C>(this, c));
142            }
143        }
144        return gens;
145    }
146
147
148    /**
149     * Query if this ring is commutative.
150     * @return true if this ring is commutative, else false.
151     */
152    public boolean isCommutative() {
153        return ring.isCommutative();
154    }
155
156
157    /**
158     * Query if this ring is associative.
159     * @return true if this ring is associative, else false.
160     */
161    public boolean isAssociative() {
162        return ring.isAssociative();
163    }
164
165
166    /**
167     * Query if this ring is a field.
168     * @return false.
169     */
170    public boolean isField() {
171        if (isField > 0) {
172            return true;
173        }
174        if (isField == 0) {
175            return false;
176        }
177        // ??
178        return false;
179    }
180
181
182    /**
183     * Characteristic of this ring.
184     * @return characteristic of this ring.
185     */
186    public java.math.BigInteger characteristic() {
187        return ring.characteristic();
188    }
189
190
191    /**
192     * Get a Local element from a BigInteger value.
193     * @param a BigInteger.
194     * @return a Local.
195     */
196    public Local<C> fromInteger(java.math.BigInteger a) {
197        return new Local<C>(this, ring.fromInteger(a));
198    }
199
200
201    /**
202     * Get a Local element from a long value.
203     * @param a long.
204     * @return a Local.
205     */
206    public Local<C> fromInteger(long a) {
207        return new Local<C>(this, ring.fromInteger(a));
208    }
209
210
211    /**
212     * Get the String representation as RingFactory.
213     * @see java.lang.Object#toString()
214     */
215    @Override
216    public String toString() {
217        return "Local[ " + ideal.toString() + " ]";
218    }
219
220
221    /**
222     * Get a scripting compatible string representation.
223     * @return script compatible representation for this ElemFactory.
224     * @see edu.jas.structure.ElemFactory#toScript()
225     */
226    @Override
227    public String toScript() {
228        // Python case
229        return "LocalRing(" + ideal.toScript() + ")";
230    }
231
232
233    /**
234     * Comparison with any other object.
235     * @see java.lang.Object#equals(java.lang.Object)
236     */
237    @Override
238    @SuppressWarnings("unchecked")
239    // not jet working
240    public boolean equals(Object b) {
241        if (b == null) {
242            return false;
243        }
244        if (!(b instanceof LocalRing)) {
245            return false;
246        }
247        LocalRing<C> a = (LocalRing<C>) b;
248        if (!ring.equals(a.ring)) {
249            return false;
250        }
251        return ideal.equals(a.ideal);
252    }
253
254
255    /**
256     * Hash code for this local ring.
257     * @see java.lang.Object#hashCode()
258     */
259    @Override
260    public int hashCode() {
261        int h;
262        h = ring.hashCode();
263        h = 37 * h + ideal.hashCode();
264        return h;
265    }
266
267
268    /**
269     * Local random.
270     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
271     * @return a random residue element.
272     */
273    public Local<C> random(int n) {
274        C r = ring.random(n);
275        C s = ring.random(n);
276        s = s.remainder(ideal);
277        while (s.isZERO()) {
278            logger.debug("zero was in ideal");
279            s = ring.random(n);
280            s = s.remainder(ideal);
281        }
282        return new Local<C>(this, r, s, false);
283    }
284
285
286    /**
287     * Local random.
288     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
289     * @param rnd is a source for random bits.
290     * @return a random residue element.
291     */
292    public Local<C> random(int n, Random rnd) {
293        C r = ring.random(n, rnd);
294        C s = ring.random(n, rnd);
295        s = s.remainder(ideal);
296        while (s.isZERO()) {
297            logger.debug("zero was in ideal");
298            s = ring.random(n, rnd);
299            s = s.remainder(ideal);
300        }
301        return new Local<C>(this, r, s, false);
302    }
303
304
305    /**
306     * Parse Local from String.
307     * @param s String.
308     * @return Local from s.
309     */
310    public Local<C> parse(String s) {
311        C x = ring.parse(s);
312        return new Local<C>(this, x);
313    }
314
315
316    /**
317     * Parse Local from Reader.
318     * @param r Reader.
319     * @return next Local from r.
320     */
321    public Local<C> parse(Reader r) {
322        C x = ring.parse(r);
323        return new Local<C>(this, x);
324    }
325
326}