001/*
002 * $Id$
003 */
004
005package edu.jas.root;
006
007
008import java.io.Serializable;
009
010import edu.jas.arith.Rational;
011import edu.jas.poly.Complex;
012import edu.jas.poly.ComplexRing;
013import edu.jas.poly.GenPolynomial;
014import edu.jas.poly.GenPolynomialRing;
015import edu.jas.poly.PolyUtil;
016import edu.jas.structure.RingElem;
017import edu.jas.structure.RingFactory;
018import edu.jas.ufd.GCDFactory;
019import edu.jas.ufd.GreatestCommonDivisor;
020
021
022/**
023 * Boundary determined by a rectangle and a polynomial.
024 * 
025 * For a given complex polynomial A a closed path through the corners of the
026 * given rectangle is constructed. The path is represented by four polynomials,
027 * one for each side of the rectangle. For a real t in [0,1] the i-th polynomial
028 * describes the path of A from corner[i] to corner[i+1]. In particular
029 * polys[i](0) = A(corner[i]) and polys[i](1) = A(corner[i+1]), with corner[4] =
030 * corner[0]. If A would be zero on a point of the path, an
031 * InvalidBoundaryException is thrown.
032 * @param <C> coefficient type.
033 * @author Heinz Kredel
034 */
035public class Boundary<C extends RingElem<C> & Rational> implements Serializable {
036
037
038    /**
039     * Rectangle.
040     */
041    public final Rectangle<C> rect;
042
043
044    /**
045     * Polynomial.
046     */
047    public final GenPolynomial<Complex<C>> A;
048
049
050    /**
051     * Boundary polynomials.
052     */
053    public final GenPolynomial<Complex<C>>[] polys;
054
055
056    /**
057     * Factory for real polynomials.
058     */
059    GenPolynomialRing<C> rfac;
060
061
062    /**
063     * Constructor.
064     * @param r rectangle of of corners.
065     * @param p non constant polynomial.
066     */
067    @SuppressWarnings("unchecked")
068    public Boundary(Rectangle<C> r, GenPolynomial<Complex<C>> p) throws InvalidBoundaryException {
069        if (p.isConstant() || p.isZERO()) {
070            throw new InvalidBoundaryException("p is constant or 0 " + p);
071        }
072        rect = r;
073        A = p;
074        GreatestCommonDivisor<Complex<C>> ufd = GCDFactory.<Complex<C>> getImplementation(A.ring.coFac);
075        polys = (GenPolynomial<Complex<C>>[]) new GenPolynomial[5];
076
077        Complex<C>[] corner = rect.corners;
078        for (int i = 0; i < 4; i++) {
079            Complex<C> t = corner[i + 1].subtract(corner[i]);
080            GenPolynomial<Complex<C>> tp = A.ring.univariate(0, 1L).multiply(t);
081            //System.out.println("t = " + t);
082            GenPolynomial<Complex<C>> pc = PolyUtil.<Complex<C>> seriesOfTaylor(A, corner[i]);
083            pc = PolyUtil.<Complex<C>> substituteUnivariate(pc, tp);
084            GenPolynomial<Complex<C>> gcd = ufd.gcd(A, pc);
085            if (!gcd.isONE()) {
086                //System.out.println("A = " + A);
087                //System.out.println("PC["+i+"] = " + pc);
088                //System.out.println("gcd = " + gcd);
089                throw new InvalidBoundaryException("A has a zero on rectangle " + rect + ", A = " + A);
090            }
091            polys[i] = pc;
092        }
093        polys[4] = polys[0];
094
095        // setup factory for real and imaginary parts
096        ComplexRing<C> cr = (ComplexRing<C>) A.ring.coFac;
097        RingFactory<C> cf = cr.ring;
098        rfac = new GenPolynomialRing<C>(cf, A.ring);
099    }
100
101
102    /**
103     * Constructor.
104     * @param r rectangle of of corners.
105     * @param p polynomial.
106     * @param b boundary polynomials.
107     */
108    protected Boundary(Rectangle<C> r, GenPolynomial<Complex<C>> p, GenPolynomial<Complex<C>>[] b) {
109        rect = r;
110        A = p;
111        polys = b;
112        // setup factory for real and imaginary parts
113        ComplexRing<C> cr = (ComplexRing<C>) A.ring.coFac;
114        RingFactory<C> cf = cr.ring;
115        rfac = new GenPolynomialRing<C>(cf, A.ring);
116    }
117
118
119    /**
120     * String representation of Boundary.
121     * @see java.lang.Object#toString()
122     */
123    @Override
124    public String toString() {
125        return rect.toString();
126    }
127
128
129    /**
130     * Get a scripting compatible string representation.
131     * @return script compatible representation for this Boundary.
132     */
133    public String toScript() {
134        // Python case
135        return rect.toScript();
136    }
137
138
139    /**
140     * Get real part for polynomial i.
141     * @param i index of polynomial.
142     * @return real part for polynomial i.
143     */
144    public GenPolynomial<C> getRealPart(int i) {
145        GenPolynomial<C> f = PolyUtil.<C> realPartFromComplex(rfac, polys[i]);
146        return f;
147    }
148
149
150    /**
151     * Get imaginary part for polynomial i.
152     * @param i index of polynomial.
153     * @return imaginary part for polynomial i.
154     */
155    public GenPolynomial<C> getImagPart(int i) {
156        GenPolynomial<C> g = PolyUtil.<C> imaginaryPartFromComplex(rfac, polys[i]);
157        return g;
158    }
159
160
161    /**
162     * Copy this.
163     * @return a copy of this.
164     */
165    public Boundary<C> copy() {
166        return new Boundary<C>(rect, A, polys);
167    }
168
169
170    /**
171     * Comparison with any other object.
172     * @see java.lang.Object#equals(java.lang.Object)
173     */
174    @Override
175    @SuppressWarnings("unchecked")
176    public boolean equals(Object b) {
177        Boundary<C> a = null;
178        try {
179            a = (Boundary<C>) b;
180        } catch (ClassCastException e) {
181        }
182        if (a == null) {
183            return false;
184        }
185        return rect.equals(a.rect) && A.equals(a.A);
186    }
187
188
189    /**
190     * Hash code for this Rectangle.
191     * @see java.lang.Object#hashCode()
192     */
193    @Override
194    public int hashCode() {
195        int hc = 0;
196        hc += 37 * rect.hashCode();
197        return 37 * hc + A.hashCode();
198    }
199
200}