001/*
002 * $Id: RealAlgebraicRing.java 3987 2012-07-14 11:58:20Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.io.Reader;
009import java.util.ArrayList;
010import java.util.List;
011import java.util.Random;
012
013import edu.jas.arith.BigDecimal;
014import edu.jas.arith.BigRational;
015import edu.jas.arith.Rational;
016import edu.jas.poly.AlgebraicNumber;
017import edu.jas.poly.AlgebraicNumberRing;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.structure.GcdRingElem;
020import edu.jas.structure.Power;
021import edu.jas.structure.RingFactory;
022
023
024/**
025 * Real algebraic number factory class based on AlgebraicNumberRing with
026 * RingElem interface. Objects of this class are immutable with the exception of
027 * the isolating intervals.
028 * @author Heinz Kredel
029 */
030
031public class RealAlgebraicRing<C extends GcdRingElem<C> & Rational>
032/*extends AlgebraicNumberRing<C>*/
033implements RingFactory<RealAlgebraicNumber<C>> {
034
035
036    /**
037     * Representing AlgebraicNumberRing.
038     */
039    public final AlgebraicNumberRing<C> algebraic;
040
041
042    /**
043     * Isolating interval for a real root. <b>Note: </b> interval may shrink
044     * eventually.
045     */
046    /*package*/Interval<C> root;
047
048
049    /**
050     * Precision of the isolating rectangle for a complex root.
051     */
052    public static final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION;
053
054
055    /**
056     * Precision of the isolating interval for a real root.
057     */
058    protected C eps;
059
060
061    /**
062     * Real root computation engine.
063     */
064    public final RealRootsSturm<C> engine;
065
066
067    /**
068     * The constructor creates a RealAlgebraicNumber factory object from a
069     * GenPolynomial objects module.
070     * @param m module GenPolynomial<C>.
071     * @param root isolating interval for a real root.
072     */
073    public RealAlgebraicRing(GenPolynomial<C> m, Interval<C> root) {
074        algebraic = new AlgebraicNumberRing<C>(m);
075        this.root = root;
076        engine = new RealRootsSturm<C>();
077        if (m.ring.characteristic().signum() > 0) {
078            throw new RuntimeException("characteristic not zero");
079        }
080        C e = m.ring.coFac.fromInteger(10L);
081        e = e.inverse();
082        //C x = Power.positivePower(e, BigDecimal.DEFAULT_PRECISION);
083        e = Power.positivePower(e, PRECISION); // better not too much for speed
084        eps = e;
085    }
086
087
088    /**
089     * The constructor creates a RealAlgebraicNumber factory object from a
090     * GenPolynomial objects module.
091     * @param m module GenPolynomial<C>.
092     * @param root isolating interval for a real root.
093     * @param isField indicator if m is prime.
094     */
095    public RealAlgebraicRing(GenPolynomial<C> m, Interval<C> root, boolean isField) {
096        algebraic = new AlgebraicNumberRing<C>(m, isField);
097        this.root = root;
098        engine = new RealRootsSturm<C>();
099        if (m.ring.characteristic().signum() > 0) {
100            throw new RuntimeException("characteristic not zero");
101        }
102        C e = m.ring.coFac.fromInteger(10L);
103        e = e.inverse();
104        e = Power.positivePower(e, PRECISION); //BigDecimal.DEFAULT_PRECISION);
105        eps = e;
106    }
107
108
109    /**
110     * Get the module part.
111     * @return modul. public GenPolynomial<C> getModul() { return
112     *         algebraic.modul; }
113     */
114
115
116    /**
117     * Get the interval for the real root. <b>Note: </b> interval may shrink
118     * later.
119     * @return real root isolating interval
120     */
121    public synchronized Interval<C> getRoot() {
122        return root;
123    }
124
125
126    /**
127     * Set a refined interval for the real root. <b>Note: </b> interval may
128     * shrink eventually.
129     * @param v interval.
130     */
131    public synchronized void setRoot(Interval<C> v) {
132        // assert v is contained in root
133        this.root = v;
134    }
135
136
137    /**
138     * Get the epsilon.
139     * @return eps.
140     */
141    public synchronized C getEps() {
142        return this.eps;
143    }
144
145
146    /**
147     * Set a new epsilon.
148     * @param e epsilon.
149     */
150    public synchronized void setEps(C e) {
151        this.eps = e;
152    }
153
154
155    /**
156     * Set a new epsilon.
157     * @param e epsilon.
158     */
159    public synchronized void setEps(BigRational e) {
160        this.eps = algebraic.ring.coFac.parse(e.toString());
161    }
162
163
164    /**
165     * RealAlgebraicRing half interval.
166     */
167    public void halfInterval() {
168        Interval<C> v = engine.halfInterval(root, algebraic.modul);
169        //System.out.println("old v = " + ring.root + ", new v = " + v);
170        setRoot(v);
171    }
172
173
174    /**
175     * Is this structure finite or infinite.
176     * @return true if this structure is finite, else false.
177     * @see edu.jas.structure.ElemFactory#isFinite()
178     */
179    public boolean isFinite() {
180        return algebraic.isFinite();
181    }
182
183
184    /**
185     * Copy RealAlgebraicNumber element c.
186     * @param c
187     * @return a copy of c.
188     */
189    public RealAlgebraicNumber<C> copy(RealAlgebraicNumber<C> c) {
190        return new RealAlgebraicNumber<C>(this, c.number);
191    }
192
193
194    /**
195     * Get the zero element.
196     * @return 0 as RealAlgebraicNumber.
197     */
198    public RealAlgebraicNumber<C> getZERO() {
199        return new RealAlgebraicNumber<C>(this, algebraic.getZERO());
200    }
201
202
203    /**
204     * Get the one element.
205     * @return 1 as RealAlgebraicNumber.
206     */
207    public RealAlgebraicNumber<C> getONE() {
208        return new RealAlgebraicNumber<C>(this, algebraic.getONE());
209    }
210
211
212    /**
213     * Get the generating element.
214     * @return alpha as RealAlgebraicNumber.
215     */
216    public RealAlgebraicNumber<C> getGenerator() {
217        return new RealAlgebraicNumber<C>(this, algebraic.getGenerator());
218    }
219
220
221    /**
222     * Get a list of the generating elements.
223     * @return list of generators for the algebraic structure.
224     * @see edu.jas.structure.ElemFactory#generators()
225     */
226    public List<RealAlgebraicNumber<C>> generators() {
227        List<AlgebraicNumber<C>> agens = algebraic.generators();
228        List<RealAlgebraicNumber<C>> gens = new ArrayList<RealAlgebraicNumber<C>>(agens.size());
229        for (AlgebraicNumber<C> a : agens) {
230            gens.add(getZERO().sum(a.getVal()));
231        }
232        return gens;
233    }
234
235
236    /**
237     * Query if this ring is commutative.
238     * @return true if this ring is commutative, else false.
239     */
240    public boolean isCommutative() {
241        return algebraic.isCommutative();
242    }
243
244
245    /**
246     * Query if this ring is associative.
247     * @return true if this ring is associative, else false.
248     */
249    public boolean isAssociative() {
250        return algebraic.isAssociative();
251    }
252
253
254    /**
255     * Query if this ring is a field.
256     * @return true if algebraic is prime, else false.
257     */
258    public boolean isField() {
259        return algebraic.isField();
260    }
261
262
263    /**
264     * Assert that this ring is a field.
265     * @param isField true if this ring is a field, else false.
266     */
267    public void setField(boolean isField) {
268        algebraic.setField(isField);
269    }
270
271
272    /**
273     * Characteristic of this ring.
274     * @return characteristic of this ring.
275     */
276    public java.math.BigInteger characteristic() {
277        return algebraic.characteristic();
278    }
279
280
281    /**
282     * Get a RealAlgebraicNumber element from a BigInteger value.
283     * @param a BigInteger.
284     * @return a RealAlgebraicNumber.
285     */
286    public RealAlgebraicNumber<C> fromInteger(java.math.BigInteger a) {
287        return new RealAlgebraicNumber<C>(this, algebraic.fromInteger(a));
288    }
289
290
291    /**
292     * Get a RealAlgebraicNumber element from a long value.
293     * @param a long.
294     * @return a RealAlgebraicNumber.
295     */
296    public RealAlgebraicNumber<C> fromInteger(long a) {
297        return new RealAlgebraicNumber<C>(this, algebraic.fromInteger(a));
298    }
299
300
301    /**
302     * Get the String representation as RingFactory.
303     * @see java.lang.Object#toString()
304     */
305    @Override
306    public String toString() {
307        return "RealAlgebraicRing[ " + algebraic.modul.toString() + " in " + root + " | isField="
308                        + algebraic.isField() + " :: " + algebraic.ring.toString() + " ]";
309    }
310
311
312    /**
313     * Get a scripting compatible string representation.
314     * @return script compatible representation for this ElemFactory.
315     * @see edu.jas.structure.ElemFactory#toScript()
316     */
317    //JAVA6only: @Override
318    public String toScript() {
319        // Python case
320        return "RealN( " + algebraic.modul.toScript() + ", " + root.toScript()
321        //+ ", " + algebraic.isField() 
322        //+ ", " + algebraic.ring.toScript() 
323                        + " )";
324    }
325
326
327    /**
328     * Comparison with any other object.
329     * @see java.lang.Object#equals(java.lang.Object)
330     */
331    @Override
332    @SuppressWarnings("unchecked")
333    // not jet working
334    public boolean equals(Object b) {
335        if (!(b instanceof RealAlgebraicRing)) {
336            return false;
337        }
338        RealAlgebraicRing<C> a = null;
339        try {
340            a = (RealAlgebraicRing<C>) b;
341        } catch (ClassCastException e) {
342        }
343        if (a == null) {
344            return false;
345        }
346        return algebraic.equals(a.algebraic) && root.equals(a.root);
347    }
348
349
350    /**
351     * Hash code for this RealAlgebraicNumber.
352     * @see java.lang.Object#hashCode()
353     */
354    @Override
355    public int hashCode() {
356        return 37 * algebraic.hashCode() + root.hashCode();
357    }
358
359
360    /**
361     * RealAlgebraicNumber random.
362     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
363     * @return a random integer mod modul.
364     */
365    public RealAlgebraicNumber<C> random(int n) {
366        return new RealAlgebraicNumber<C>(this, algebraic.random(n));
367    }
368
369
370    /**
371     * RealAlgebraicNumber random.
372     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
373     * @param rnd is a source for random bits.
374     * @return a random integer mod modul.
375     */
376    public RealAlgebraicNumber<C> random(int n, Random rnd) {
377        return new RealAlgebraicNumber<C>(this, algebraic.random(n, rnd));
378    }
379
380
381    /**
382     * Parse RealAlgebraicNumber from String.
383     * @param s String.
384     * @return RealAlgebraicNumber from s.
385     */
386    public RealAlgebraicNumber<C> parse(String s) {
387        return new RealAlgebraicNumber<C>(this, algebraic.parse(s));
388    }
389
390
391    /**
392     * Parse RealAlgebraicNumber from Reader.
393     * @param r Reader.
394     * @return next RealAlgebraicNumber from r.
395     */
396    public RealAlgebraicNumber<C> parse(Reader r) {
397        return new RealAlgebraicNumber<C>(this, algebraic.parse(r));
398    }
399
400}