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