001/*
002 * $Id: Factors.java 3329 2010-09-19 19:02:10Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.io.Serializable;
009import java.util.List;
010import java.util.ArrayList;
011
012import edu.jas.poly.AlgebraicNumber;
013import edu.jas.poly.AlgebraicNumberRing;
014import edu.jas.poly.GenPolynomial;
015import edu.jas.poly.GenPolynomialRing;
016import edu.jas.poly.PolynomialList;
017import edu.jas.structure.GcdRingElem;
018
019
020/**
021 * Container for the factors of absolute factorization.
022 * @author Heinz Kredel
023 * @param <C> coefficient type
024 */
025
026public class Factors<C extends GcdRingElem<C>> implements Comparable<Factors<C>>, Serializable {
027
028
029    /**
030     * Original (irreducible) polynomial to be factored with coefficients from C.
031     */
032    public final GenPolynomial<C> poly;
033
034
035    /**
036     * Algebraic field extension over C. Should be null, if p is absolutely
037     * irreducible.
038     */
039    public final AlgebraicNumberRing<C> afac;
040
041
042    /**
043     * Original polynomial to be factored with coefficients from
044     * AlgebraicNumberRing&lt;C&gt;. Should be null, if p is absolutely irreducible.
045     */
046    public final GenPolynomial<AlgebraicNumber<C>> apoly;
047
048
049    /**
050     * List of factors with coefficients from AlgebraicNumberRing&lt;C&gt;. Should be
051     * null, if p is absolutely irreducible.
052     */
053    public final List<GenPolynomial<AlgebraicNumber<C>>> afactors;
054
055
056    /**
057     * List of factors with coefficients from AlgebraicNumberRing&lt;AlgebraicNumber&lt;C&gt;&gt;.
058     * Should be null, if p is absolutely irreducible.
059     */
060    public final List<Factors<AlgebraicNumber<C>>> arfactors;
061
062
063    /**
064     * Constructor.
065     * @param p absolute irreducible GenPolynomial.
066     */
067    public Factors(GenPolynomial<C> p) {
068        this(p, null, null, null, null);
069    }
070
071
072    /**
073     * Constructor.
074     * @param p irreducible GenPolynomial over C.
075     * @param af algebraic extension field of C where p has factors from afact.
076     * @param ap GenPolynomial p represented with coefficients from af.
077     * @param afact absolute irreducible factors of p with coefficients from af.
078     */
079    public Factors(GenPolynomial<C> p, AlgebraicNumberRing<C> af, GenPolynomial<AlgebraicNumber<C>> ap,
080            List<GenPolynomial<AlgebraicNumber<C>>> afact) {
081        this(p, af, ap, afact, null);
082    }
083
084
085    /**
086     * Constructor.
087     * @param p irreducible GenPolynomial over C.
088     * @param af algebraic extension field of C where p has factors from afact.
089     * @param ap GenPolynomial p represented with coefficients from af.
090     * @param afact absolute irreducible factors of p with coefficients from af.
091     * @param arfact further absolute irreducible factors of p with coefficients from extensions of af.
092     */
093    public Factors(GenPolynomial<C> p, AlgebraicNumberRing<C> af, GenPolynomial<AlgebraicNumber<C>> ap,
094            List<GenPolynomial<AlgebraicNumber<C>>> afact, List<Factors<AlgebraicNumber<C>>> arfact) {
095        poly = p;
096        afac = af;
097        apoly = ap;
098        afactors = afact;
099        arfactors = arfact;
100    }
101
102
103    /**
104     * Get the String representation.
105     * @see java.lang.Object#toString()
106     */
107    @Override
108    public String toString() {
109        StringBuffer sb = new StringBuffer();
110        sb.append(poly.toString());
111        if (afac == null) {
112            return sb.toString();
113        }
114        sb.append(" = ");
115        boolean first = true;
116        for (GenPolynomial<AlgebraicNumber<C>> ap : afactors) {
117            if (first) {
118                first = false;
119            } else {
120                sb.append(", ");
121            }
122            sb.append(ap.toString());
123        }
124        sb.append("\n  ## over " + afac.toString() + "\n");
125        if (arfactors == null) {
126            return sb.toString();
127        }
128        first = true;
129        for (Factors<AlgebraicNumber<C>> arp : arfactors) {
130            if (first) {
131                first = false;
132            } else {
133                sb.append(",\n");
134            }
135            sb.append(arp.toString());
136        }
137        return sb.toString();
138    }
139
140
141    /**
142     * Get a scripting compatible string representation.
143     * @return script compatible representation for this container.
144     * @see edu.jas.structure.ElemFactory#toScript()
145     */
146    public String toScript() {
147        // Python case
148        StringBuffer sb = new StringBuffer();
149        //sb.append(poly.toScript());
150        if (afac == null) {
151            return sb.toString();
152        }
153        //sb.append(" =\n");
154        boolean first = true;
155        for (GenPolynomial<AlgebraicNumber<C>> ap : afactors) {
156            if (first) {
157                first = false;
158            } else {
159                sb.append("\n * ");
160            }
161            //sb.append("( " + ap.toScript() + " )");
162            sb.append(ap.toScript());
163        }
164        sb.append("   ## over " + afac.toScript() + "\n");
165        if (arfactors == null) {
166            return sb.toString();
167        }
168        first = true;
169        for (Factors<AlgebraicNumber<C>> arp : arfactors) {
170            if (first) {
171                first = false;
172            } else {
173                sb.append("\n * ");
174            }
175            sb.append(arp.toScript());
176        }
177        return sb.toString();
178    }
179
180
181    /**
182     * Hash code for this Factors.
183     * @see java.lang.Object#hashCode()
184     */
185    @Override
186    public int hashCode() {
187        int h;
188        h = poly.hashCode();
189        if (afac == null) {
190            return h;
191        }
192        h = (h << 27);
193        h += afac.hashCode();
194        if ( afactors != null ) {
195            h = (h << 27);
196            h += afactors.hashCode();
197        }
198        if ( arfactors != null ) {
199            h = (h << 27);
200            h += arfactors.hashCode();
201        }
202        return h;
203    }
204
205
206    /**
207     * Comparison with any other object.
208     * @see java.lang.Object#equals(java.lang.Object)
209     */
210    @Override
211    @SuppressWarnings("unchecked")
212    public boolean equals(Object B) {
213        if (!(B instanceof Factors)) {
214            return false;
215        }
216        Factors<C> a = null;
217        try {
218            a = (Factors<C>) B;
219        } catch (ClassCastException ignored) {
220        }
221        if (a == null) {
222            return false;
223        }
224        return this.compareTo(a) == 0;
225    }
226
227
228    /**
229     * Comparison.
230     * @param facs factors container.
231     * @return sign(this.poly-facs.poly) lexicographic &gt;
232     *         sign(afac.modul-facs.afac.modul) 
233     *         lexicographic &gt; afactors.compareTo(facs.afactors)
234     *         lexicographic &gt; arfactors[i].compareTo(facs.arfactors[i])
235     */
236    public int compareTo(Factors<C> facs) {
237        int s = poly.compareTo(facs.poly);
238        //System.out.println("s1 = " + s); 
239        if (s != 0) {
240            return s;
241        }
242        if (afac == null) {
243            return -1;
244        }
245        if (facs.afac == null) {
246            return +1;
247        }
248        s = afac.modul.compareTo(facs.afac.modul);
249        //System.out.println("s2 = " + s); 
250        if ( s != 0 ) {
251            return s;
252        }
253        GenPolynomialRing<AlgebraicNumber<C>> ar = afactors.get(0).ring;
254        GenPolynomialRing<AlgebraicNumber<C>> br = facs.afactors.get(0).ring;
255        PolynomialList<AlgebraicNumber<C>> ap = new PolynomialList<AlgebraicNumber<C>>(ar,afactors);
256        PolynomialList<AlgebraicNumber<C>> bp = new PolynomialList<AlgebraicNumber<C>>(br,facs.afactors);
257        s = ap.compareTo(bp);
258        //System.out.println("s3 = " + s); 
259        if ( s != 0 ) {
260            return s;
261        }
262        if (arfactors == null && facs.arfactors == null) {
263            return 0;
264        }
265        if (arfactors == null) {
266            return -1;
267        }
268        if (facs.arfactors == null) {
269            return +1;
270        }
271        // lexicographic (?)
272        int i = 0;
273        for (Factors<AlgebraicNumber<C>> arp : arfactors) {
274            if ( i >= facs.arfactors.size() ) {
275                return +1;
276            }
277            Factors<AlgebraicNumber<C>> brp = facs.arfactors.get(i);
278            //System.out.println("arp = " + arp); 
279            //System.out.println("brp = " + brp); 
280            s = arp.compareTo(brp);
281            //System.out.println("s4 = " + s); 
282            if ( s != 0 ) {
283                return s;
284            }
285            i++;
286        }
287        if ( i < facs.arfactors.size() ) {
288            return -1;
289        }
290        return 0;
291    }
292
293
294    /**
295     * Find largest extension field.
296     * @return largest extension field or null if no extension field
297     */
298    @SuppressWarnings("unchecked")
299    public AlgebraicNumberRing<C> findExtensionField() {
300        if (afac == null) {
301            return null;
302        }
303        if (arfactors == null) {
304            return afac;
305        }
306        AlgebraicNumberRing<C> arr = afac;
307        int depth = 1;
308        for (Factors<AlgebraicNumber<C>> af : arfactors) {
309            AlgebraicNumberRing<AlgebraicNumber<C>> aring = af.findExtensionField();
310            if (aring == null) {
311                continue;
312            }
313            int d = aring.depth();
314            if (d > depth) {
315                depth = d;
316                arr = (AlgebraicNumberRing<C>) (Object) aring;
317            }
318        }
319        return arr;
320    }
321
322
323    /**
324     * Get the list of factors at one level.
325     * @return list of algebraic factors 
326     */
327    public List<GenPolynomial<AlgebraicNumber<C>>> getFactors() {
328        List<GenPolynomial<AlgebraicNumber<C>>> af = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>();
329        if ( afac == null ) {
330            return af;
331        }
332        af.addAll(afactors);
333        if ( arfactors == null ) {
334            return af;
335        }
336        for (Factors<AlgebraicNumber<C>> arp : arfactors) {
337            af.add( arp.poly );
338        }
339        return af;
340    }
341
342
343    /**
344     * Get the factor for polynomial.
345     * @return algebraic factor 
346     */
347    public Factors<AlgebraicNumber<C>> getFactor(GenPolynomial<AlgebraicNumber<C>> p) {
348        if ( afac == null ) {
349            return null;
350        }
351        for (Factors<AlgebraicNumber<C>> arp : arfactors) {
352            if ( p.equals( arp.poly ) ) {
353                return arp;
354            }
355        }
356        return null;
357    }
358
359}