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