001    /*
002     * $Id: PartialFraction.java 3295 2010-08-26 17:01:10Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import java.io.Serializable;
009    import java.util.List;
010    
011    import edu.jas.poly.AlgebraicNumber;
012    import edu.jas.poly.AlgebraicNumberRing;
013    import edu.jas.poly.GenPolynomial;
014    import edu.jas.structure.GcdRingElem;
015    
016    
017    /**
018     * Container for the partial fraction decomposition of a squarefree denominator.
019     * num/den = sum( a_i ( der(d_i) / d_i ) )
020     * @author Heinz Kredel
021     * @param <C> coefficient type
022     */
023    
024    public class PartialFraction<C extends GcdRingElem<C>> implements Serializable {
025    
026    
027        /**
028         * Original numerator polynomial coefficients from C and deg(num) &lt;
029         * deg(den).
030         */
031        public final GenPolynomial<C> num;
032    
033    
034        /**
035         * Original (irreducible) denominator polynomial coefficients from C.
036         */
037        public final GenPolynomial<C> den;
038    
039    
040        /**
041         * List of numbers from C.
042         */
043        public final List<C> cfactors;
044    
045    
046        /**
047         * List of linear factors of the denominator with coefficients from C.
048         */
049        public final List<GenPolynomial<C>> cdenom;
050    
051    
052        /**
053         * List of algebraic numbers of an algebraic field extension over C.
054         */
055        public final List<AlgebraicNumber<C>> afactors;
056    
057    
058        /**
059         * List of factors of the denominator with coefficients from an
060         * AlgebraicNumberRing&lt;C&gt;.
061         */
062        public final List<GenPolynomial<AlgebraicNumber<C>>> adenom;
063    
064    
065        /**
066         * Constructor.
067         * @param n numerator GenPolynomial over C.
068         * @param d irreducible denominator GenPolynomial over C.
069         * @param cf list of elements a_i.
070         * @param cd list of linear factors d_i of d.
071         * @param af list of algebraic elements a_i.
072         * @param ad list of irreducible factors d_i of d with algebraic
073         *            coefficients. n/d = sum( a_i ( der(d_i) / d_i ) )
074         */
075        public PartialFraction(GenPolynomial<C> n, GenPolynomial<C> d, List<C> cf, List<GenPolynomial<C>> cd,
076                List<AlgebraicNumber<C>> af, List<GenPolynomial<AlgebraicNumber<C>>> ad) {
077            num = n;
078            den = d;
079            cfactors = cf;
080            cdenom = cd;
081            afactors = af;
082            adenom = ad;
083        }
084    
085    
086        /**
087         * Get the String representation.
088         * @see java.lang.Object#toString()
089         */
090        @Override
091        public String toString() {
092            StringBuffer sb = new StringBuffer();
093            sb.append("(" + num.toString() + ")");
094            sb.append(" / ");
095            sb.append("(" + den.toString() + ")");
096            sb.append(" =\n");
097            boolean first = true;
098            for (int i = 0; i < cfactors.size(); i++) {
099                C cp = cfactors.get(i);
100                if (first) {
101                    first = false;
102                } else {
103                    sb.append(" + ");
104                }
105                sb.append("(" + cp.toString() + ")");
106                GenPolynomial<C> p = cdenom.get(i);
107                sb.append(" log( " + p.toString() + ")");
108            }
109            if (!first && afactors.size() > 0) {
110                sb.append(" + ");
111            }
112            first = true;
113            for (int i = 0; i < afactors.size(); i++) {
114                if (first) {
115                    first = false;
116                } else {
117                    sb.append(" + ");
118                }
119                AlgebraicNumber<C> ap = afactors.get(i);
120                AlgebraicNumberRing<C> ar = ap.factory();
121                //sb.append(" ## over " + ap.factory() + "\n");
122                GenPolynomial<AlgebraicNumber<C>> p = adenom.get(i);
123                if (p.degree(0) < ar.modul.degree(0) && ar.modul.degree(0) > 2) {
124                    sb.append("sum_(" + ar.getGenerator() + " in ");
125                    sb.append("rootOf(" + ar.modul + ") ) ");
126                } else {
127                    //sb.append("sum_("+ar+") ");
128                }
129                sb.append("(" + ap.toString() + ")");
130                sb.append(" log( " + p.toString() + ")");
131            }
132            return sb.toString();
133        }
134    
135    
136        /**
137         * Get the String representation.
138         * @see java.lang.Object#toString()
139         */
140        //@Override
141        public String toStringX() {
142            StringBuffer sb = new StringBuffer();
143            sb.append("(" + num.toString() + ")");
144            sb.append(" / ");
145            sb.append("(" + den.toString() + ")");
146            sb.append(" =\n");
147            boolean first = true;
148            for (C cp : cfactors) {
149                if (first) {
150                    first = false;
151                } else {
152                    sb.append(", ");
153                }
154                sb.append(cp.toString());
155            }
156            if (!first) {
157                sb.append(" linear denominators: ");
158            }
159            first = true;
160            for (GenPolynomial<C> cp : cdenom) {
161                if (first) {
162                    first = false;
163                } else {
164                    sb.append(", ");
165                }
166                sb.append(cp.toString());
167            }
168            if (!first) {
169                sb.append("; ");
170            }
171            first = true;
172            for (AlgebraicNumber<C> ap : afactors) {
173                if (first) {
174                    first = false;
175                } else {
176                    //sb.append(", ");
177                }
178                sb.append(ap.toString());
179                sb.append(" ## over " + ap.factory() + "\n");
180            }
181            if (!first) {
182                sb.append(" denominators: ");
183            }
184            first = true;
185            for (GenPolynomial<AlgebraicNumber<C>> ap : adenom) {
186                if (first) {
187                    first = false;
188                } else {
189                    sb.append(", ");
190                }
191                sb.append(ap.toString());
192            }
193            return sb.toString();
194        }
195    
196    
197        /**
198         * Get a scripting compatible string representation.
199         * @return script compatible representation for this container.
200         * @see edu.jas.structure.ElemFactory#toScript()
201         */
202        public String toScript() {
203            // Python case
204            StringBuffer sb = new StringBuffer();
205    
206            sb.append(num.toScript());
207            sb.append(" / ");
208            sb.append(den.toScript());
209            sb.append(" = ");
210            boolean first = true;
211            for (C cp : cfactors) {
212                if (first) {
213                    first = false;
214                } else {
215                    sb.append(", ");
216                }
217                sb.append(cp.toScript());
218            }
219            if (!first) {
220                sb.append(" linear denominators: ");
221            }
222            first = true;
223            for (GenPolynomial<C> cp : cdenom) {
224                if (first) {
225                    first = false;
226                } else {
227                    sb.append(", ");
228                }
229                sb.append(cp.toScript());
230            }
231            if (!first) {
232                sb.append(", ");
233            }
234            first = true;
235            for (AlgebraicNumber<C> ap : afactors) {
236                if (first) {
237                    first = false;
238                } else {
239                    //sb.append(", ");
240                }
241                sb.append(ap.toScript());
242                sb.append(" ## over " + ap.toScriptFactory() + "\n");
243            }
244            sb.append(" denominators: ");
245            first = true;
246            for (GenPolynomial<AlgebraicNumber<C>> ap : adenom) {
247                if (first) {
248                    first = false;
249                } else {
250                    sb.append(", ");
251                }
252                sb.append(ap.toScript());
253            }
254            return sb.toString();
255        }
256    
257    
258        /**
259         * Hash code for this Factors.
260         * @see java.lang.Object#hashCode()
261         */
262        @Override
263        public int hashCode() {
264            int h = num.hashCode();
265            h = h * 37 + den.hashCode();
266            h = h * 37 + cfactors.hashCode();
267            h = h * 37 + cdenom.hashCode();
268            h = h * 37 + afactors.hashCode();
269            h = h * 37 + adenom.hashCode();
270            return h;
271        }
272    
273    
274        /**
275         * Comparison with any other object.
276         * @see java.lang.Object#equals(java.lang.Object)
277         */
278        @Override
279        @SuppressWarnings("unchecked")
280        public boolean equals(Object B) {
281            if (!(B instanceof PartialFraction)) {
282                return false;
283            }
284            PartialFraction<C> a = null;
285            try {
286                a = (PartialFraction<C>) B;
287            } catch (ClassCastException ignored) {
288            }
289            if (a == null) {
290                return false;
291            }
292            boolean t = num.equals(a.num) && den.equals(a.den);
293            if (!t) {
294                return t;
295            }
296            t = cfactors.equals(a.cfactors);
297            if (!t) {
298                return t;
299            }
300            t = cdenom.equals(a.cdenom);
301            if (!t) {
302                return t;
303            }
304            t = afactors.equals(a.afactors);
305            if (!t) {
306                return t;
307            }
308            t = adenom.equals(a.adenom);
309            return t;
310        }
311    
312    }