001/*
002 * $Id$
003 */
004
005package edu.jas.ufd;
006
007
008import java.io.Serializable;
009import java.util.SortedMap;
010import java.util.Map;
011
012import edu.jas.poly.AlgebraicNumberRing;
013import edu.jas.poly.GenPolynomial;
014import edu.jas.structure.GcdRingElem;
015
016
017/**
018 * Container for the factors of a eventually non-squarefree factorization.
019 * @author Heinz Kredel
020 * @param <C> coefficient type
021 */
022
023public class FactorsMap<C extends GcdRingElem<C>> implements Serializable {
024
025
026    /**
027     * Original polynomial to be factored with coefficients from C.
028     */
029    public final GenPolynomial<C> poly;
030
031
032    /**
033     * List of factors with coefficients from C.
034     */
035    public final SortedMap<GenPolynomial<C>, Long> factors;
036
037
038    /**
039     * List of factors with coefficients from AlgebraicNumberRings.
040     */
041    public final SortedMap<Factors<C>, Long> afactors;
042
043
044    /**
045     * Constructor.
046     * @param p given GenPolynomial over C.
047     * @param map irreducible factors of p with coefficients from C.
048     */
049    public FactorsMap(GenPolynomial<C> p, SortedMap<GenPolynomial<C>, Long> map) {
050        this(p, map, null);
051    }
052
053
054    /**
055     * Constructor.
056     * @param p given GenPolynomial over C.
057     * @param map irreducible factors of p with coefficients from C.
058     * @param amap irreducible factors of p with coefficients from an algebraic
059     *            number field.
060     */
061    public FactorsMap(GenPolynomial<C> p, SortedMap<GenPolynomial<C>, Long> map,
062                    SortedMap<Factors<C>, Long> amap) {
063        poly = p;
064        factors = map;
065        afactors = amap;
066    }
067
068
069    /**
070     * Get the String representation.
071     * @see java.lang.Object#toString()
072     */
073    @Override
074    public String toString() {
075        StringBuffer sb = new StringBuffer();
076        sb.append(poly.toString());
077        sb.append(" =\n");
078        boolean first = true;
079        for (Map.Entry<GenPolynomial<C>,Long> me : factors.entrySet()) {
080            GenPolynomial<C> p = me.getKey();
081            if (first) {
082                first = false;
083            } else {
084                sb.append(",\n ");
085            }
086            sb.append(p.toString());
087            long e = me.getValue();
088            if (e > 1) {
089                sb.append("**" + e);
090            }
091        }
092        if (afactors == null) {
093            return sb.toString();
094        }
095        for (Map.Entry<Factors<C>,Long> me : afactors.entrySet()) {
096            Factors<C> f = me.getKey();
097            if (first) {
098                first = false;
099            } else {
100                sb.append(",\n ");
101            }
102            sb.append(f.toString());
103            Long e = me.getValue();
104            if (e == null) {
105                continue;
106            }
107            if (e > 1) {
108                sb.append("**" + e);
109            }
110        }
111        return sb.toString();
112    }
113
114
115    /**
116     * Get a scripting compatible string representation.
117     * @return script compatible representation for this container.
118     * @see edu.jas.structure.ElemFactory#toScript()
119     */
120    public String toScript() {
121        // Python case
122        StringBuffer sb = new StringBuffer();
123        //sb.append(poly.toScript());
124        //sb.append(" =\n");
125        boolean first = true;
126        for (Map.Entry<GenPolynomial<C>,Long> me : factors.entrySet()) {
127            GenPolynomial<C> p = me.getKey();
128            if (first) {
129                first = false;
130            } else {
131                sb.append("\n * ");
132            }
133            sb.append(p.toScript());
134            long e = me.getValue();
135            if (e > 1) {
136                sb.append("**" + e);
137            }
138        }
139        if (afactors == null) {
140            return sb.toString();
141        }
142        for (Map.Entry<Factors<C>,Long> me : afactors.entrySet()) {
143            Factors<C> f = me.getKey();
144            if (first) {
145                first = false;
146            } else {
147                sb.append("\n * ");
148            }
149            Long e = me.getValue();
150            if (e == null) { // should not happen
151                System.out.println("f = " + f);
152                System.out.println("afactors = " + afactors);
153                throw new RuntimeException("this should not happen");
154            }
155            if (e == 1) {
156                sb.append(f.toScript());
157            } else {
158                sb.append("(\n");
159                sb.append(f.toScript());
160                sb.append("\n)**" + e);
161            }
162        }
163        return sb.toString();
164    }
165
166
167    /**
168     * Length. Number of factors.
169     * @return number of distinct factors.
170     */
171    public int length() {
172        int i = factors.keySet().size();
173        if (afactors == null) {
174            return i;
175        }
176        for (Factors<C> f : afactors.keySet()) {
177             i += f.length();
178        }
179        return i;
180    }
181
182
183    /**
184     * Find largest extension field.
185     * @return largest extension field or null if no extension field
186     */
187    public AlgebraicNumberRing<C> findExtensionField() {
188        if (afactors == null) {
189            return null;
190        }
191        AlgebraicNumberRing<C> ar = null;
192        int depth = 0;
193        for (Factors<C> f : afactors.keySet()) {
194            AlgebraicNumberRing<C> aring = f.findExtensionField();
195            if (aring == null) {
196                continue;
197            }
198            int d = aring.depth();
199            if (d > depth) {
200                depth = d;
201                ar = aring;
202            }
203        }
204        return ar;
205    }
206
207}