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