001/*
002 * $Id: AlgebraicRoots.java 5579 2016-08-14 17:48:18Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.io.Serializable;
009import java.util.List;
010
011import edu.jas.arith.Rational;
012import edu.jas.poly.AlgebraicNumberRing;
013import edu.jas.poly.GenPolynomial;
014import edu.jas.poly.Complex;
015import edu.jas.structure.GcdRingElem;
016
017
018/**
019 * Container for the real and complex algebraic roots of a univariate
020 * polynomial.
021 * @param <C> coefficient type.
022 * @author Heinz Kredel
023 */
024public class AlgebraicRoots<C extends GcdRingElem<C> & Rational> implements Serializable {
025
026
027    /**
028     * Univariate polynomial.
029     */
030    public final GenPolynomial<C> p;
031
032
033    /**
034     * Real algebraic roots.
035     */
036    public final List<RealAlgebraicNumber<C>> real;
037
038
039    /**
040     * Univariate polynomial with complex coefficients equivalent to p.
041     */
042    public final GenPolynomial<Complex<C>> cp;
043
044
045    /**
046     * Complex algebraic roots.
047     */
048    public final List<ComplexAlgebraicNumber<C>> complex;
049
050
051    /**
052     * Constructor not for use.
053     */
054    protected AlgebraicRoots() {
055        throw new IllegalArgumentException("do not use this constructor");
056    }
057
058
059    /**
060     * Constructor.
061     * @param p univariate polynomial
062     * @param cp univariate polynomial with compelx coefficients
063     * @param r list of real algebraic roots
064     * @param c list of complex algebraic roots
065     */
066    public AlgebraicRoots(GenPolynomial<C> p, GenPolynomial<Complex<C>> cp, List<RealAlgebraicNumber<C>> r,
067                    List<ComplexAlgebraicNumber<C>> c) {
068        this.p = p;
069        this.cp = cp;
070        this.real = r;
071        this.complex = c;
072    }
073
074
075    /**
076     * String representation of AlgebraicRoots.
077     * @see java.lang.Object#toString()
078     */
079    @Override
080    public String toString() {
081        return "[" + p + ", real=" + real + ", complex=" + complex + "]";
082    }
083
084
085    /**
086     * Get a scripting compatible string representation.
087     * @return script compatible representation for this roots.
088     */
089    public String toScript() {
090        // Python case
091        StringBuffer sb = new StringBuffer("[");
092        sb.append(p.toScript());
093        //sb.append(", ");
094        //sb.append(cp.toScript());
095        if (!real.isEmpty()) {
096            sb.append(", real=[");
097            boolean first = true;
098            for (RealAlgebraicNumber<C> r : real) {
099                if (first) {
100                    first = false;
101                } else {
102                    sb.append(", ");
103                }
104                sb.append(r.toScript());
105            }
106            sb.append("]");
107        }
108        if (!complex.isEmpty()) {
109            sb.append(", complex=[");
110            boolean first = true;
111            for (ComplexAlgebraicNumber<C> c : complex) {
112                if (first) {
113                    first = false;
114                } else {
115                    sb.append(", ");
116                }
117                sb.append(c.toScript());
118            }
119            sb.append("]");
120        }
121        sb.append("]");
122        return sb.toString();
123    }
124
125
126    /**
127     * Get a decimal number scripting compatible string representation.
128     * @return decimal number script compatible representation for this roots.
129     */
130    public String toDecimalScript() {
131        // Python case
132        StringBuffer sb = new StringBuffer("[");
133        sb.append(p.toScript());
134        //sb.append(", ");
135        //sb.append(cp.toScript());
136        if (!real.isEmpty()) {
137            sb.append(", real=[");
138            boolean first = true;
139            for (RealAlgebraicNumber<C> r : real) {
140                if (first) {
141                    first = false;
142                } else {
143                    sb.append(", ");
144                }
145                sb.append(r.ring.root.toDecimal().toScript());
146            }
147            sb.append("]");
148        }
149        if (!complex.isEmpty()) {
150            sb.append(", complex=[");
151            boolean first = true;
152            for (ComplexAlgebraicNumber<C> c : complex) {
153                if (first) {
154                    first = false;
155                } else {
156                    sb.append(", ");
157                }
158                sb.append(c.ring.root.getDecimalCenter().toScript());
159            }
160            sb.append("]");
161        }
162        sb.append("]");
163        return sb.toString();
164    }
165
166
167    /**
168     * Copy this.
169     * @return a copy of this.
170     */
171    public AlgebraicRoots<C> copy() {
172        return new AlgebraicRoots<C>(p, cp, real, complex);
173    }
174
175
176    /**
177     * Comparison with any other object.
178     * @see java.lang.Object#equals(java.lang.Object)
179     */
180    @Override
181    @SuppressWarnings("unchecked")
182    public boolean equals(Object b) {
183        if (!(b instanceof AlgebraicRoots)) {
184            return false;
185        }
186        AlgebraicRoots<C> a = null;
187        try {
188            a = (AlgebraicRoots<C>) b;
189        } catch (ClassCastException e) {
190            return false;
191        }
192        // && cp.equals(a.cp)
193        return p.equals(a.p) && real.equals(a.real) && complex.equals(a.complex);
194    }
195
196
197    /**
198     * Hash code for this AlgebraicRoots.
199     * @see java.lang.Object#hashCode()
200     */
201    @Override
202    public int hashCode() {
203        return (161 * p.hashCode() + 37) * real.hashCode() + complex.hashCode();
204    }
205
206
207    /**
208     * Algebraic number ring.
209     * @return algebraic ring of roots.
210     */
211    public AlgebraicNumberRing<C> getAlgebraicRing() {
212        AlgebraicNumberRing<C> anr = new AlgebraicNumberRing<C>(p);
213        return anr;
214    }
215}