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