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