001/*
002 * $Id$
003 */
004
005package edu.jas.poly;
006
007
008import java.io.Reader;
009import java.math.BigInteger;
010import java.util.ArrayList;
011import java.util.List;
012import java.util.Random;
013
014import org.apache.logging.log4j.LogManager;
015import org.apache.logging.log4j.Logger;
016
017import edu.jas.kern.StringUtil;
018import edu.jas.structure.RingElem;
019import edu.jas.structure.RingFactory;
020
021
022/**
023 * Generic Complex ring factory implementing the RingFactory interface. Objects
024 * of this class are immutable.
025 * @param <C> base type.
026 * @author Heinz Kredel
027 */
028public class ComplexRing<C extends RingElem<C>> implements RingFactory<Complex<C>> {
029
030
031    private final static Random random = new Random();
032
033
034    @SuppressWarnings("unused")
035    private static final Logger logger = LogManager.getLogger(ComplexRing.class);
036
037
038    /**
039     * Complex class elements factory data structure.
040     */
041    public final RingFactory<C> ring;
042
043
044    /**
045     * The constructor creates a ComplexRing object.
046     * @param ring factory for Complex real and imaginary parts.
047     */
048    public ComplexRing(RingFactory<C> ring) {
049        this.ring = ring;
050    }
051
052
053    /**
054     * Get a list of the generating elements.
055     * @return list of generators for the algebraic structure.
056     * @see edu.jas.structure.ElemFactory#generators()
057     */
058    public List<Complex<C>> generators() {
059        List<C> gens = ring.generators();
060        List<Complex<C>> g = new ArrayList<Complex<C>>(gens.size() + 1);
061        for (C x : gens) {
062            Complex<C> cx = new Complex<C>(this, x);
063            g.add(cx);
064        }
065        g.add(getIMAG());
066        return g;
067    }
068
069
070    /**
071     * Corresponding algebraic number ring.
072     * @return algebraic number ring. not jet possible.
073     */
074    public AlgebraicNumberRing<C> algebraicRing() {
075        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(ring, TermOrderByName.INVLEX, new String[] { "I" });
076        GenPolynomial<C> I = pfac.univariate(0, 2L).sum(pfac.getONE());
077        AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(I, ring.isField()); // must indicate field
078        return afac;
079    }
080
081
082    /**
083     * Is this structure finite or infinite.
084     * @return true if this structure is finite, else false.
085     * @see edu.jas.structure.ElemFactory#isFinite()
086     */
087    public boolean isFinite() {
088        return ring.isFinite();
089    }
090
091
092    /**
093     * Copy Complex element c.
094     * @param c Complex&lt;C&gt;.
095     * @return a copy of c.
096     */
097    public Complex<C> copy(Complex<C> c) {
098        return new Complex<C>(this, c.re, c.im);
099    }
100
101
102    /**
103     * Get the zero element.
104     * @return 0 as Complex&lt;C&gt;.
105     */
106    public Complex<C> getZERO() {
107        return new Complex<C>(this);
108    }
109
110
111    /**
112     * Get the one element.
113     * @return 1 as Complex&lt;C&gt;.
114     */
115    public Complex<C> getONE() {
116        return new Complex<C>(this, ring.getONE());
117    }
118
119
120    /**
121     * Get the i element.
122     * @return i as Complex&lt;C&gt;.
123     */
124    public Complex<C> getIMAG() {
125        return new Complex<C>(this, ring.getZERO(), ring.getONE());
126    }
127
128
129    /**
130     * Query if this ring is commutative.
131     * @return true.
132     */
133    public boolean isCommutative() {
134        return ring.isCommutative();
135    }
136
137
138    /**
139     * Query if this ring is associative.
140     * @return true.
141     */
142    public boolean isAssociative() {
143        return ring.isAssociative();
144    }
145
146
147    /**
148     * Query if this ring is a field.
149     * @return true.
150     */
151    public boolean isField() {
152        return ring.isField();
153    }
154
155
156    /**
157     * Characteristic of this ring.
158     * @return characteristic of this ring.
159     */
160    public java.math.BigInteger characteristic() {
161        return ring.characteristic();
162    }
163
164
165    /**
166     * Get a Complex element from a BigInteger.
167     * @param a BigInteger.
168     * @return a Complex&lt;C&gt;.
169     */
170    public Complex<C> fromInteger(BigInteger a) {
171        return new Complex<C>(this, ring.fromInteger(a));
172    }
173
174
175    /**
176     * Get a Complex element from a long.
177     * @param a long.
178     * @return a Complex&lt;C&gt;.
179     */
180    public Complex<C> fromInteger(long a) {
181        return new Complex<C>(this, ring.fromInteger(a));
182    }
183
184
185    /**
186     * Get the String representation.
187     */
188    @Override
189    public String toString() {
190        StringBuffer sb = new StringBuffer();
191        sb.append("Complex[");
192        if (ring instanceof RingElem) {
193            RingElem ri = (RingElem) ring;
194            sb.append(ri.toScriptFactory());
195        } else {
196            sb.append(ring.toString());
197        }
198        sb.append("]");
199        return sb.toString();
200    }
201
202
203    /**
204     * Get a scripting compatible string representation.
205     * @return script compatible representation for this Element.
206     * @see edu.jas.structure.Element#toScript()
207     */
208    @Override
209    public String toScript() {
210        // Python case
211        StringBuffer s = new StringBuffer();
212        s.append("CR(");
213        if (ring instanceof RingElem) {
214            RingElem ri = (RingElem) ring;
215            s.append(ri.toScriptFactory());
216        } else {
217            s.append(ring.toScript());
218        }
219        s.append(")");
220        return s.toString();
221    }
222
223
224    /**
225     * Comparison with any other object.
226     * @see java.lang.Object#equals(java.lang.Object)
227     */
228    @Override
229    @SuppressWarnings("unchecked")
230    public boolean equals(Object b) {
231        if (b == null) {
232            return false;
233        }
234        if (!(b instanceof ComplexRing)) {
235            return false;
236        }
237        ComplexRing<C> a = (ComplexRing<C>) b;
238        if (!ring.equals(a.ring)) {
239            return false;
240        }
241        return true;
242    }
243
244
245    /**
246     * Hash code for this ComplexRing&lt;C&gt;.
247     * @see java.lang.Object#hashCode()
248     */
249    @Override
250    public int hashCode() {
251        return ring.hashCode();
252    }
253
254
255    /**
256     * Complex number random. Random base numbers A and B are generated using
257     * random(n). Then R is the complex number with real part A and imaginary
258     * part B.
259     * @param n such that 0 &le; A, B &le; (2<sup>n</sup>-1).
260     * @return R.
261     */
262    public Complex<C> random(int n) {
263        return random(n, random);
264        //         C r = ring.random( n ).abs();
265        //         C i = ring.random( n ).abs();
266        //         return new Complex<C>(this, r, i ); 
267    }
268
269
270    /**
271     * Complex number random. Random base numbers A and B are generated using
272     * random(n). Then R is the complex number with real part A and imaginary
273     * part B.
274     * @param n such that 0 &le; A, B &le; (2<sup>n</sup>-1).
275     * @param rnd is a source for random bits.
276     * @return R.
277     */
278    public Complex<C> random(int n, Random rnd) {
279        C r = ring.random(n, rnd);
280        C i = ring.random(n, rnd);
281        return new Complex<C>(this, r, i);
282    }
283
284
285    /**
286     * Parse complex number from string.
287     * @param s String.
288     * @return Complex<C> from s.
289     */
290    public Complex<C> parse(String s) {
291        return new Complex<C>(this, s);
292    }
293
294
295    /**
296     * Parse complex number from Reader.
297     * @param r Reader.
298     * @return next Complex<C> from r.
299     */
300    public Complex<C> parse(Reader r) {
301        return parse(StringUtil.nextString(r));
302    }
303
304}