001    /*
002     * $Id: RealAlgebraicRing.java 3753 2011-08-27 20:34:30Z kredel $
003     */
004    
005    package edu.jas.application;
006    
007    
008    import java.io.Reader;
009    import java.util.ArrayList;
010    import java.util.List;
011    import java.util.Random;
012    
013    import org.apache.log4j.Logger;
014    
015    import edu.jas.kern.Scripting;
016    import edu.jas.arith.BigRational;
017    import edu.jas.arith.Rational;
018    import edu.jas.poly.AlgebraicNumber;
019    import edu.jas.poly.AlgebraicNumberRing;
020    import edu.jas.poly.PolyUtil;
021    import edu.jas.poly.TermOrder;
022    import edu.jas.poly.GenPolynomial;
023    import edu.jas.poly.GenPolynomialRing;
024    import edu.jas.root.RealRootTuple;
025    import edu.jas.root.PolyUtilRoot;
026    import edu.jas.root.Interval;
027    import edu.jas.structure.GcdRingElem;
028    import edu.jas.structure.Power;
029    import 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    
040    public 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         * Characteristic of this ring.
282         * @return characteristic of this ring.
283         */
284        public java.math.BigInteger characteristic() {
285            return realRing.characteristic();
286        }
287    
288    
289        /**
290         * Get a RealAlgebraicNumber element from a BigInteger value.
291         * @param a BigInteger.
292         * @return a RealAlgebraicNumber.
293         */
294        public RealAlgebraicNumber<C> fromInteger(java.math.BigInteger a) {
295            return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a));
296        }
297    
298    
299        /**
300         * Get a RealAlgebraicNumber element from a long value.
301         * @param a long.
302         * @return a RealAlgebraicNumber.
303         */
304        public RealAlgebraicNumber<C> fromInteger(long a) {
305            return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a));
306        }
307    
308    
309        /**
310         * Get the String representation as RingFactory.
311         * @see java.lang.Object#toString()
312         */
313        @Override
314        public String toString() {
315            return "RealAlgebraicRing[ " + realRing.toString() + " in " + root + " | isField="
316                            + realRing.isField() + " :: " + algebraic.ideal.toString() + " ]";
317        }
318    
319    
320        /**
321         * Get a scripting compatible string representation.
322         * @return script compatible representation for this ElemFactory.
323         * @see edu.jas.structure.ElemFactory#toScript()
324         */
325        //JAVA6only: @Override
326        public String toScript() {
327            // Python case
328            return "RealRecN( " + realRing.toScript() + ", " + root.toScript()
329            //+ ", " + realRing.isField() 
330            //+ ", " + realRing.ring.toScript() 
331                            + " )";
332        }
333    
334    
335        /**
336         * Comparison with any other object.
337         * @see java.lang.Object#equals(java.lang.Object)
338         */
339        @Override
340        @SuppressWarnings("unchecked")
341        // not jet working
342        public boolean equals(Object b) {
343            if (!(b instanceof RealAlgebraicRing)) {
344                return false;
345            }
346            RealAlgebraicRing<C> a = null;
347            try {
348                a = (RealAlgebraicRing<C>) b;
349            } catch (ClassCastException e) {
350            }
351            if (a == null) {
352                return false;
353            }
354            return realRing.equals(a.realRing) && root.equals(a.root);
355        }
356    
357    
358        /**
359         * Hash code for this RealAlgebraicNumber.
360         * @see java.lang.Object#hashCode()
361         */
362        @Override
363        public int hashCode() {
364            return 37 * realRing.hashCode() + root.hashCode();
365        }
366    
367    
368        /**
369         * RealAlgebraicNumber random.
370         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
371         * @return a random integer mod modul.
372         */
373        public RealAlgebraicNumber<C> random(int n) {
374            return new RealAlgebraicNumber<C>(this, realRing.random(n));
375        }
376    
377    
378        /**
379         * RealAlgebraicNumber random.
380         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
381         * @param rnd is a source for random bits.
382         * @return a random integer mod modul.
383         */
384        public RealAlgebraicNumber<C> random(int n, Random rnd) {
385            return new RealAlgebraicNumber<C>(this, realRing.random(n, rnd));
386        }
387    
388    
389        /**
390         * Parse RealAlgebraicNumber from String.
391         * @param s String.
392         * @return RealAlgebraicNumber from s.
393         */
394        public RealAlgebraicNumber<C> parse(String s) {
395            return new RealAlgebraicNumber<C>(this, realRing.parse(s));
396        }
397    
398    
399        /**
400         * Parse RealAlgebraicNumber from Reader.
401         * @param r Reader.
402         * @return next RealAlgebraicNumber from r.
403         */
404        public RealAlgebraicNumber<C> parse(Reader r) {
405            return new RealAlgebraicNumber<C>(this, realRing.parse(r));
406        }
407    
408    }