001/*
002 * $Id: RealAlgebraicRing.java 4655 2013-10-05 10:12:32Z 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.kern.Scripting;
016import edu.jas.arith.BigRational;
017import edu.jas.arith.Rational;
018import edu.jas.poly.AlgebraicNumber;
019import edu.jas.poly.AlgebraicNumberRing;
020import edu.jas.poly.PolyUtil;
021import edu.jas.poly.TermOrder;
022import edu.jas.poly.GenPolynomial;
023import edu.jas.poly.GenPolynomialRing;
024import edu.jas.root.RealRootTuple;
025import edu.jas.root.PolyUtilRoot;
026import edu.jas.root.Interval;
027import edu.jas.structure.GcdRingElem;
028import edu.jas.structure.Power;
029import edu.jas.structure.RingFactory;
030
031
032/**
033 * Real algebraic number factory class based on bi-variate real algebraic
034 * numbers. Objects of this class are immutable with the exception of the
035 * isolating intervals. Bi-variate ideal implementation is in version 3614
036 * 2011-04-28 09:20:34Z.
037 * @author Heinz Kredel
038 */
039
040public class RealAlgebraicRing<C extends GcdRingElem<C> & Rational> implements
041                RingFactory<RealAlgebraicNumber<C>> {
042
043
044    /**
045     * Representing ideal with univariate polynomials IdealWithUniv.
046     */
047    /*package*/final IdealWithUniv<C> univs;
048
049
050    /**
051     * Representing ResidueRing.
052     */
053    /*package*/final ResidueRing<C> algebraic;
054
055
056    /**
057     * Isolating intervals for the real algebraic roots of the real and
058     * imaginary part. <b>Note: </b> intervals may shrink eventually.
059     */
060    /*package*/RealRootTuple<C> root;
061
062
063    /**
064     * Recursive real root ring.
065     */
066    public final edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> realRing;
067
068
069    /**
070     * Epsilon of the isolating rectangle for a complex root.
071     */
072    protected C eps;
073
074
075    /**
076     * Precision of the isolating rectangle for a complex root.
077     */
078    public final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION;
079
080
081    private static final Logger logger = Logger.getLogger(RealAlgebraicRing.class);
082
083
084    /**
085     * The constructor creates a RealAlgebraicNumber factory object from a
086     * IdealWithUniv, ResidueRing and a root tuple.
087     * @param m module IdealWithUniv&lt;C&gt;.
088     * @param a module ResidueRing&lt;C&gt;.
089     * @param r isolating rectangle for a complex root.
090     */
091    public RealAlgebraicRing(IdealWithUniv<C> m, ResidueRing<C> a, RealRootTuple<C> r) {
092        univs = m;
093        algebraic = a;
094        root = r;
095        if (algebraic.characteristic().signum() > 0) {
096            throw new IllegalArgumentException("characteristic not zero");
097        }
098        C e = m.ideal.list.ring.coFac.fromInteger(10L);
099        e = e.inverse();
100        e = Power.positivePower(e, PRECISION);
101        eps = e;
102        edu.jas.root.RealAlgebraicRing<C> rfac1 = root.tuple.get(0).factory();
103        edu.jas.root.RealAlgebraicRing<C> rfac2 = root.tuple.get(1).factory();
104        GenPolynomial<C> p0 = PolyUtil.<C> selectWithVariable(univs.ideal.list.list, 0);
105        if (p0 == null) {
106            throw new RuntimeException("no polynomial found in " + (0) + " of  " + univs.ideal);
107        }
108        //System.out.println("realRing, pol = " + p0.toScript());
109        GenPolynomialRing<C> pfac = p0.ring;
110        GenPolynomialRing<GenPolynomial<C>> prfac = pfac.recursive(1);
111        //System.out.println("prfac = " + prfac);
112        GenPolynomial<GenPolynomial<C>> p0r = PolyUtil.<C> recursive(prfac,p0);
113        GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>> parfac 
114            = new GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>>(rfac1,prfac);
115        GenPolynomial<edu.jas.root.RealAlgebraicNumber<C>> p0ar 
116           = PolyUtilRoot.<C> convertRecursiveToAlgebraicCoefficients(parfac,p0r);
117        Interval<C> r2 = rfac2.getRoot();
118        edu.jas.root.RealAlgebraicNumber<C> rleft = rfac1.getZERO().sum(r2.left);
119        edu.jas.root.RealAlgebraicNumber<C> rright = rfac1.getZERO().sum(r2.right);
120        Interval<edu.jas.root.RealAlgebraicNumber<C>> r2r = new Interval<edu.jas.root.RealAlgebraicNumber<C>>(rleft,rright);
121        edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> rr 
122            = new edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>>(p0ar,r2r); 
123        logger.info("realRing = " + rr);
124        realRing = rr;
125    }
126
127
128    /**
129     * The constructor creates a RealAlgebraicNumber factory object from a
130     * IdealWithUniv and a root tuple.
131     * @param m module IdealWithUniv&lt;C&gt;.
132     * @param root isolating rectangle for a complex root.
133     */
134    public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root) {
135        this(m, new ResidueRing<C>(m.ideal), root);
136    }
137
138
139    /**
140     * The constructor creates a RealAlgebraicNumber factory object from a
141     * IdealWithUniv and a root tuple.
142     * @param m module IdealWithUniv&lt;C&gt;.
143     * @param root isolating rectangle for a complex root.
144     * @param isField indicator if m is maximal.
145     */
146    public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root, boolean isField) {
147        this(m, new ResidueRing<C>(m.ideal, isField), root);
148    }
149
150
151    /**
152     * Set a refined rectangle for the complex root. <b>Note: </b> rectangle may
153     * shrink eventually.
154     * @param v rectangle.
155     */
156    public synchronized void setRoot(RealRootTuple<C> v) {
157        // assert v is contained in root
158        this.root = v;
159    }
160
161
162    /**
163     * Get rectangle for the complex root.
164     * @return v rectangle.
165     */
166    public synchronized RealRootTuple<C> getRoot() {
167        return this.root;
168    }
169
170
171    /**
172     * Get epsilon.
173     * @return epsilon.
174     */
175    public synchronized C getEps() {
176        return this.eps;
177    }
178
179
180    /**
181     * Set a new epsilon.
182     * @param e epsilon.
183     */
184    public synchronized void setEps(C e) {
185        this.eps = e;
186    }
187
188
189    /**
190     * Set a new epsilon.
191     * @param e epsilon.
192     */
193    public synchronized void setEps(BigRational e) {
194        edu.jas.root.RealAlgebraicRing<C> r = (edu.jas.root.RealAlgebraicRing<C>) realRing.algebraic.ring.coFac;
195        this.eps = r.algebraic.ring.coFac.parse(e.toString());
196    }
197
198
199    /**
200     * Is this structure finite or infinite.
201     * @return true if this structure is finite, else false.
202     * @see edu.jas.structure.ElemFactory#isFinite()
203     */
204    public boolean isFinite() {
205        return realRing.isFinite();
206    }
207
208
209    /**
210     * Copy RealAlgebraicNumber element c.
211     * @param c
212     * @return a copy of c.
213     */
214    public RealAlgebraicNumber<C> copy(RealAlgebraicNumber<C> c) {
215        return new RealAlgebraicNumber<C>(this, c.number);
216    }
217
218
219    /**
220     * Get the zero element.
221     * @return 0 as RealAlgebraicNumber.
222     */
223    public RealAlgebraicNumber<C> getZERO() {
224        return new RealAlgebraicNumber<C>(this, realRing.getZERO());
225    }
226
227
228    /**
229     * Get the one element.
230     * @return 1 as RealAlgebraicNumber.
231     */
232    public RealAlgebraicNumber<C> getONE() {
233        return new RealAlgebraicNumber<C>(this, realRing.getONE());
234    }
235
236
237    /**
238     * Get a list of the generating elements.
239     * @return list of generators for the algebraic structure.
240     * @see edu.jas.structure.ElemFactory#generators()
241     */
242    public List<RealAlgebraicNumber<C>> generators() {
243        List<edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>>> agens = realRing
244                        .generators();
245        List<RealAlgebraicNumber<C>> gens = new ArrayList<RealAlgebraicNumber<C>>(agens.size());
246        for (edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>> a : agens) {
247            gens.add(getZERO().sum(a));
248        }
249        return gens;
250    }
251
252
253    /**
254     * Query if this ring is commutative.
255     * @return true if this ring is commutative, else false.
256     */
257    public boolean isCommutative() {
258        return realRing.isCommutative();
259    }
260
261
262    /**
263     * Query if this ring is associative.
264     * @return true if this ring is associative, else false.
265     */
266    public boolean isAssociative() {
267        return realRing.isAssociative();
268    }
269
270
271    /**
272     * Query if this ring is a field.
273     * @return true if algebraic is prime, else false.
274     */
275    public boolean isField() {
276        return realRing.isField();
277    }
278
279
280    /**
281     * Assert that this ring is a field.
282     * @param isField true if this ring is a field, else false.
283     */
284    public void setField(boolean isField) {
285        realRing.setField(isField);
286    }
287
288
289    /**
290     * Characteristic of this ring.
291     * @return characteristic of this ring.
292     */
293    public java.math.BigInteger characteristic() {
294        return realRing.characteristic();
295    }
296
297
298    /**
299     * Get a RealAlgebraicNumber element from a BigInteger value.
300     * @param a BigInteger.
301     * @return a RealAlgebraicNumber.
302     */
303    public RealAlgebraicNumber<C> fromInteger(java.math.BigInteger a) {
304        return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a));
305    }
306
307
308    /**
309     * Get a RealAlgebraicNumber element from a long value.
310     * @param a long.
311     * @return a RealAlgebraicNumber.
312     */
313    public RealAlgebraicNumber<C> fromInteger(long a) {
314        return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a));
315    }
316
317
318    /**
319     * Get the String representation as RingFactory.
320     * @see java.lang.Object#toString()
321     */
322    @Override
323    public String toString() {
324        return "RealAlgebraicRing[ " + realRing.toString() + " in " + root + " | isField="
325                        + realRing.isField() + ", algebraic.ideal=" + algebraic.ideal.toString() + " ]";
326    }
327
328
329    /**
330     * Get a scripting compatible string representation.
331     * @return script compatible representation for this ElemFactory.
332     * @see edu.jas.structure.ElemFactory#toScript()
333     */
334    @Override
335    public String toScript() {
336        // Python case
337        return "RealRecN( " + realRing.toScript() + ", " + root.toScript()
338        //+ ", " + realRing.isField() 
339        //+ ", " + realRing.ring.toScript() 
340                        + " )";
341    }
342
343
344    /**
345     * Comparison with any other object.
346     * @see java.lang.Object#equals(java.lang.Object)
347     */
348    @Override
349    @SuppressWarnings("unchecked")
350    // not jet working
351    public boolean equals(Object b) {
352        if (!(b instanceof RealAlgebraicRing)) {
353            return false;
354        }
355        RealAlgebraicRing<C> a = null;
356        try {
357            a = (RealAlgebraicRing<C>) b;
358        } catch (ClassCastException e) {
359        }
360        if (a == null) {
361            return false;
362        }
363        return realRing.equals(a.realRing) && 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 * realRing.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, realRing.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, realRing.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, realRing.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, realRing.parse(r));
415    }
416
417}