001/*
002 * $Id: RealAlgebraicRing.java 5734 2017-02-18 20:30:54Z kredel $
003 */
004
005package edu.jas.application;
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.arith.BigRational;
016import edu.jas.arith.Rational;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019import edu.jas.poly.PolyUtil;
020import edu.jas.root.Interval;
021import edu.jas.root.PolyUtilRoot;
022import edu.jas.root.RealRootTuple;
023import edu.jas.structure.GcdRingElem;
024import edu.jas.structure.RingFactory;
025
026
027/**
028 * Real algebraic number factory class based on bi-variate real algebraic
029 * numbers. Objects of this class are immutable with the exception of the
030 * isolating intervals. Bi-variate ideal implementation is in version 3614
031 * 2011-04-28 09:20:34Z.
032 * @author Heinz Kredel
033 */
034
035public class RealAlgebraicRing<C extends GcdRingElem<C> & Rational>
036                implements RingFactory<RealAlgebraicNumber<C>> {
037
038
039    /**
040     * Representing ideal with univariate polynomials IdealWithUniv.
041     */
042    /*package*/final IdealWithUniv<C> univs;
043
044
045    /**
046     * Representing ResidueRing.
047     */
048    /*package*/final ResidueRing<C> algebraic;
049
050
051    /**
052     * Isolating intervals for the real algebraic roots of the real and
053     * imaginary part. <b>Note: </b> intervals may shrink eventually.
054     */
055    /*package*/RealRootTuple<C> root;
056
057
058    /**
059     * Recursive real root ring.
060     */
061    public final edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> realRing;
062
063
064    /**
065     * Epsilon of the isolating rectangle for a complex root.
066     */
067    protected BigRational eps;
068
069
070    /**
071     * Precision of the isolating rectangle for a complex root.
072     */
073    public final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION;
074
075
076    private static final Logger logger = Logger.getLogger(RealAlgebraicRing.class);
077
078
079    /**
080     * The constructor creates a RealAlgebraicNumber factory object from a
081     * IdealWithUniv, ResidueRing and a root tuple.
082     * @param m module IdealWithUniv&lt;C&gt;.
083     * @param a module ResidueRing&lt;C&gt;.
084     * @param r isolating rectangle for a complex root.
085     */
086    public RealAlgebraicRing(IdealWithUniv<C> m, ResidueRing<C> a, RealRootTuple<C> r) {
087        univs = m;
088        algebraic = a;
089        root = r;
090        if (algebraic.characteristic().signum() > 0) {
091            throw new IllegalArgumentException("characteristic not zero");
092        }
093        if (root.tuple.size() != 2) {
094            throw new IllegalArgumentException("wrong tuple size: " + root.tuple.size());
095        }
096        eps = BigRational.ONE;
097        edu.jas.root.RealAlgebraicRing<C> rfac1 = root.tuple.get(0).factory();
098        edu.jas.root.RealAlgebraicRing<C> rfac2 = root.tuple.get(1).factory();
099        GenPolynomial<C> p0 = PolyUtil.<C> selectWithVariable(univs.ideal.list.list, 0);
100        if (p0 == null) {
101            throw new RuntimeException("no polynomial found in " + (0) + " of  " + univs.ideal);
102        }
103        //System.out.println("realRing, pol = " + p0.toScript());
104        GenPolynomialRing<C> pfac = p0.ring;
105        GenPolynomialRing<GenPolynomial<C>> prfac = pfac.recursive(1);
106        //System.out.println("prfac = " + prfac);
107        GenPolynomial<GenPolynomial<C>> p0r = PolyUtil.<C> recursive(prfac, p0);
108        GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>> parfac = new GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>>(
109                        rfac1, prfac);
110        GenPolynomial<edu.jas.root.RealAlgebraicNumber<C>> p0ar = PolyUtilRoot
111                        .<C> convertRecursiveToAlgebraicCoefficients(parfac, p0r);
112        Interval<C> r2 = rfac2.getRoot();
113        edu.jas.root.RealAlgebraicNumber<C> rleft = rfac1.getZERO().sum(r2.left);
114        edu.jas.root.RealAlgebraicNumber<C> rright = rfac1.getZERO().sum(r2.right);
115        Interval<edu.jas.root.RealAlgebraicNumber<C>> r2r = new Interval<edu.jas.root.RealAlgebraicNumber<C>>(
116                        rleft, rright);
117        edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> rr = new edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>>(
118                        p0ar, r2r);
119        logger.info("realRing = " + rr);
120        realRing = rr;
121    }
122
123
124    /**
125     * The constructor creates a RealAlgebraicNumber factory object from a
126     * IdealWithUniv and a root tuple.
127     * @param m module IdealWithUniv&lt;C&gt;.
128     * @param root isolating rectangle for a complex root.
129     */
130    public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root) {
131        this(m, new ResidueRing<C>(m.ideal), root);
132    }
133
134
135    /**
136     * The constructor creates a RealAlgebraicNumber factory object from a
137     * IdealWithUniv and a root tuple.
138     * @param m module IdealWithUniv&lt;C&gt;.
139     * @param root isolating rectangle for a complex root.
140     * @param isField indicator if m is maximal.
141     */
142    public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root, boolean isField) {
143        this(m, new ResidueRing<C>(m.ideal, isField), root);
144    }
145
146
147    /**
148     * Set a refined rectangle for the complex root. <b>Note: </b> rectangle may
149     * shrink eventually.
150     * @param v rectangle.
151     */
152    public synchronized void setRoot(RealRootTuple<C> v) {
153        assert root.contains(v) : "root contains v";
154        this.root = v;
155    }
156
157
158    /**
159     * Get rectangle for the complex root.
160     * @return v rectangle.
161     */
162    public synchronized RealRootTuple<C> getRoot() {
163        return this.root;
164    }
165
166
167    /**
168     * Get epsilon.
169     * @return epsilon.
170     */
171    public synchronized BigRational getEps() {
172        return this.eps;
173    }
174
175
176    /**
177     * Set a new epsilon.
178     * @param e epsilon.
179     */
180    public synchronized void setEps(C e) {
181        setEps(e.getRational());
182    }
183
184
185    /**
186     * Set a new epsilon.
187     * @param e epsilon.
188     */
189    public synchronized void setEps(BigRational e) {
190        this.eps = e;
191    }
192
193
194    /**
195     * Refine root.
196     * @param e epsilon.
197     */
198    public synchronized void refineRoot(BigRational e) {
199        setEps(e);
200        root.refineRoot(this.eps);
201    }
202
203
204    /**
205     * Is this structure finite or infinite.
206     * @return true if this structure is finite, else false.
207     * @see edu.jas.structure.ElemFactory#isFinite()
208     */
209    public boolean isFinite() {
210        return realRing.isFinite();
211    }
212
213
214    /**
215     * Copy RealAlgebraicNumber element c.
216     * @param c
217     * @return a copy of c.
218     */
219    public RealAlgebraicNumber<C> copy(RealAlgebraicNumber<C> c) {
220        return new RealAlgebraicNumber<C>(this, c.number);
221    }
222
223
224    /**
225     * Get the zero element.
226     * @return 0 as RealAlgebraicNumber.
227     */
228    public RealAlgebraicNumber<C> getZERO() {
229        return new RealAlgebraicNumber<C>(this, realRing.getZERO());
230    }
231
232
233    /**
234     * Get the one element.
235     * @return 1 as RealAlgebraicNumber.
236     */
237    public RealAlgebraicNumber<C> getONE() {
238        return new RealAlgebraicNumber<C>(this, realRing.getONE());
239    }
240
241
242    /**
243     * Get a list of the generating elements.
244     * @return list of generators for the algebraic structure.
245     * @see edu.jas.structure.ElemFactory#generators()
246     */
247    public List<RealAlgebraicNumber<C>> generators() {
248        List<edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>>> agens = realRing
249                        .generators();
250        List<RealAlgebraicNumber<C>> gens = new ArrayList<RealAlgebraicNumber<C>>(agens.size());
251        for (edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>> a : agens) {
252            gens.add(getZERO().sum(a));
253        }
254        return gens;
255    }
256
257
258    /**
259     * Query if this ring is commutative.
260     * @return true if this ring is commutative, else false.
261     */
262    public boolean isCommutative() {
263        return realRing.isCommutative();
264    }
265
266
267    /**
268     * Query if this ring is associative.
269     * @return true if this ring is associative, else false.
270     */
271    public boolean isAssociative() {
272        return realRing.isAssociative();
273    }
274
275
276    /**
277     * Query if this ring is a field.
278     * @return true if algebraic is prime, else false.
279     */
280    public boolean isField() {
281        return realRing.isField();
282    }
283
284
285    /**
286     * Assert that this ring is a field.
287     * @param isField true if this ring is a field, else false.
288     */
289    public void setField(boolean isField) {
290        realRing.setField(isField);
291    }
292
293
294    /**
295     * Characteristic of this ring.
296     * @return characteristic of this ring.
297     */
298    public java.math.BigInteger characteristic() {
299        return realRing.characteristic();
300    }
301
302
303    /**
304     * Get a RealAlgebraicNumber element from a BigInteger value.
305     * @param a BigInteger.
306     * @return a RealAlgebraicNumber.
307     */
308    public RealAlgebraicNumber<C> fromInteger(java.math.BigInteger a) {
309        return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a));
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, realRing.fromInteger(a));
320    }
321
322
323    /**
324     * Get the String representation as RingFactory.
325     * @see java.lang.Object#toString()
326     */
327    @Override
328    public synchronized String toString() {
329        return "RealAlgebraicRing[ " + realRing.toString() + " in " + root + " | isField="
330                        + realRing.isField() + ", algebraic.ideal=" + algebraic.ideal.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 synchronized String toScript() {
341        // Python case
342        return "RealRecN( " + realRing.toScript() + ", " + root.toScript()
343        //+ ", " + realRing.isField() 
344        //+ ", " + realRing.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 synchronized boolean equals(Object b) {
356        if (!(b instanceof RealAlgebraicRing)) {
357            return false;
358        }
359        RealAlgebraicRing<C> a = null;
360        try {
361            a = (RealAlgebraicRing<C>) b;
362        } catch (ClassCastException e) {
363        }
364        if (a == null) {
365            return false;
366        }
367        return realRing.equals(a.realRing) && root.equals(a.getRoot());
368    }
369
370
371    /**
372     * Hash code for this RealAlgebraicNumber.
373     * @see java.lang.Object#hashCode()
374     */
375    @Override
376    public synchronized int hashCode() {
377        return 37 * realRing.hashCode() + root.hashCode();
378    }
379
380
381    /**
382     * RealAlgebraicNumber random.
383     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
384     * @return a random integer mod modul.
385     */
386    public RealAlgebraicNumber<C> random(int n) {
387        return new RealAlgebraicNumber<C>(this, realRing.random(n));
388    }
389
390
391    /**
392     * RealAlgebraicNumber random.
393     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
394     * @param rnd is a source for random bits.
395     * @return a random integer mod modul.
396     */
397    public RealAlgebraicNumber<C> random(int n, Random rnd) {
398        return new RealAlgebraicNumber<C>(this, realRing.random(n, rnd));
399    }
400
401
402    /**
403     * Parse RealAlgebraicNumber from String.
404     * @param s String.
405     * @return RealAlgebraicNumber from s.
406     */
407    public RealAlgebraicNumber<C> parse(String s) {
408        return new RealAlgebraicNumber<C>(this, realRing.parse(s));
409    }
410
411
412    /**
413     * Parse RealAlgebraicNumber from Reader.
414     * @param r Reader.
415     * @return next RealAlgebraicNumber from r.
416     */
417    public RealAlgebraicNumber<C> parse(Reader r) {
418        return new RealAlgebraicNumber<C>(this, realRing.parse(r));
419    }
420
421}