001/*
002 * $Id$
003 */
004
005package edu.jas.application;
006
007
008import java.io.IOException;
009import java.io.Serializable;
010import java.io.StringReader;
011import java.util.List;
012
013import edu.jas.arith.Rational;
014import edu.jas.arith.PrimeInteger;
015import edu.jas.poly.AlgebraicNumberRing;
016import edu.jas.poly.Complex;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019import edu.jas.poly.GenPolynomialTokenizer;
020import edu.jas.poly.TermOrder;
021import edu.jas.root.ComplexAlgebraicRing;
022import edu.jas.root.Interval;
023import edu.jas.root.RealAlgebraicRing;
024import edu.jas.root.Rectangle;
025import edu.jas.root.RootUtil;
026import edu.jas.structure.RingElem;
027import edu.jas.structure.RingFactory;
028import edu.jas.ufd.QuotientRing;
029import edu.jas.ufd.PolyUfdUtil;
030import edu.jas.vector.GenMatrixRing;
031
032
033/**
034 * Builder for extension field towers.
035 * @author Heinz Kredel
036 */
037public class ExtensionFieldBuilder implements Serializable {
038
039
040    /**
041     * The current factory.
042     */
043    public final RingFactory factory; // must be a raw type
044
045
046    /**
047     * Constructor not for use.
048     */
049    protected ExtensionFieldBuilder() {
050        throw new IllegalArgumentException("do not use this constructor");
051    }
052
053
054    /**
055     * Constructor.
056     * @param base the base field.
057     */
058    public ExtensionFieldBuilder(RingFactory base) {
059        factory = base;
060    }
061
062
063    /**
064     * Build the field tower. TODO: optimize field tower for faster
065     * computation.
066     */
067    public RingFactory build() {
068        return factory;
069    }
070
071
072    /**
073     * Set base field.
074     * @param base the base field for the extensions.
075     */
076    public static ExtensionFieldBuilder baseField(RingFactory base) {
077        return new ExtensionFieldBuilder(base);
078    }
079
080
081    /**
082     * Transcendent field extension.
083     * @param vars names for the transcendent generators.
084     */
085    @SuppressWarnings("unchecked")
086    public ExtensionFieldBuilder transcendentExtension(String vars) {
087        String[] variables = GenPolynomialTokenizer.variableList(vars);
088        GenPolynomialRing pfac = new GenPolynomialRing(factory, variables);
089        QuotientRing qfac = new QuotientRing(pfac);
090        RingFactory base = (RingFactory) qfac;
091        return new ExtensionFieldBuilder(base);
092    }
093
094
095    /**
096     * Polynomial ring extension.
097     * @param vars names for the polynomial ring generators.
098     */
099    @SuppressWarnings("unchecked")
100    public ExtensionFieldBuilder polynomialExtension(String vars) {
101        String[] variables = GenPolynomialTokenizer.variableList(vars);
102        GenPolynomialRing pfac = new GenPolynomialRing(factory, variables);
103        RingFactory base = (RingFactory) pfac;
104        return new ExtensionFieldBuilder(base);
105    }
106
107
108    /**
109     * Matrix ring extension.
110     * @param n dimension of n x n matrix.
111     */
112    @SuppressWarnings("unchecked")
113    public ExtensionFieldBuilder matrixExtension(int n) {
114        GenMatrixRing mfac = new GenMatrixRing(factory, n, n);
115        RingFactory base = (RingFactory) mfac;
116        return new ExtensionFieldBuilder(base);
117    }
118
119
120    /**
121     * Finite field extension.
122     * Construct a finite field with q = p**n elements, where
123     * p is the characteristic of the base field.
124     * @param n exponent.
125     */
126    @SuppressWarnings("unchecked")
127    public ExtensionFieldBuilder finiteFieldExtension(int n) {
128        java.math.BigInteger p = factory.characteristic();
129        if (p.signum() != 1) {
130            throw new IllegalArgumentException("characteristic not finite");
131        }
132        if (!PrimeInteger.isPrime(p)) { //??
133            throw new IllegalArgumentException("characteristic not prime");
134        }
135        RingFactory base = (RingFactory) PolyUfdUtil.algebraicNumberField(factory,n);
136        return new ExtensionFieldBuilder(base);
137    }
138
139
140    /**
141     * Algebraic field extension.
142     * @param var name(s) for the algebraic generator(s).
143     * @param expr generating expression, a univariate or multivariate polynomial
144     *            in vars.
145     */
146    @SuppressWarnings("unchecked")
147    public ExtensionFieldBuilder algebraicExtension(String var, String expr) {
148        String[] variables = GenPolynomialTokenizer.variableList(var);
149        if (variables.length < 1) {
150            variables = GenPolynomialTokenizer.expressionVariables(expr);
151            if (variables.length < 1) {
152                throw new IllegalArgumentException("no variables in '" + var + "' and '" + expr + "'");
153            }
154        }
155        GenPolynomialRing pfac = new GenPolynomialRing(factory, variables);
156        if (variables.length == 1) { // simple extension
157            GenPolynomial gen = pfac.parse(expr);
158            AlgebraicNumberRing afac = new AlgebraicNumberRing(gen);
159            RingFactory base = (RingFactory) afac;
160            return new ExtensionFieldBuilder(base);
161        }
162        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(pfac, new StringReader(expr));
163        List<GenPolynomial> gen = null;
164        try {
165            gen = pt.nextPolynomialList();
166        } catch (IOException e) { // should not happen
167            throw new IllegalArgumentException(e);
168        }
169        Ideal agen = new Ideal(pfac, gen);
170        if (agen.isONE()) {
171            throw new IllegalArgumentException("ideal is 1: " + expr);
172        }
173        if (agen.isZERO()) { // transcendent extension
174            QuotientRing qfac = new QuotientRing(pfac);
175            RingFactory base = (RingFactory) qfac;
176            return new ExtensionFieldBuilder(base);
177        }
178        // check if agen is prime?
179        ResidueRing afac = new ResidueRing(agen);
180        RingFactory base = (RingFactory) afac;
181        return new ExtensionFieldBuilder(base);
182    }
183
184
185    /**
186     * Real algebraic field extension.
187     * @param var name for the algebraic generator.
188     * @param expr generating expression, a univariate polynomial in var.
189     * @param root isolating interval for a real root.
190     */
191    @SuppressWarnings("unchecked")
192    public ExtensionFieldBuilder realAlgebraicExtension(String var, String expr, String root) {
193        String[] variables = new String[] { var };
194        RingElem one = (RingElem) factory.getONE();
195        if (!(one instanceof Rational)) {
196            throw new IllegalArgumentException("base field not instance of Rational");
197        }
198        TermOrder to = new TermOrder(TermOrder.INVLEX);
199        GenPolynomialRing pfac = new GenPolynomialRing(factory, to, variables);
200        GenPolynomial gen = pfac.parse(expr);
201        RingFactory cf = pfac.coFac;
202        Interval iv = RootUtil.parseInterval(cf, root);
203        //System.out.println("iv = " + iv);
204        RealAlgebraicRing rfac = new RealAlgebraicRing(gen, iv);
205        RingFactory base = (RingFactory) rfac;
206        return new ExtensionFieldBuilder(base);
207    }
208
209
210    /**
211     * Complex algebraic field extension.
212     * @param var name for the algebraic generator.
213     * @param expr generating expression, a univariate polynomial in var.
214     * @param root isolating rectangle for a complex root.
215     */
216    @SuppressWarnings("unchecked")
217    public ExtensionFieldBuilder complexAlgebraicExtension(String var, String expr, String root) {
218        String[] variables = new String[] { var };
219        RingElem one = (RingElem) factory.getONE();
220        if (!(one instanceof Complex)) {
221            throw new IllegalArgumentException("base field not instance of Complex");
222        }
223        GenPolynomialRing pfac = new GenPolynomialRing(factory, variables);
224        //System.out.println("pfac = " + pfac);
225        GenPolynomial gen = pfac.parse(expr);
226        //System.out.println("gen  = " + gen);
227        RingFactory cf = pfac.coFac;
228        Rectangle rt = RootUtil.parseRectangle(cf, root);
229        //System.out.println("rt = " + rt);
230        ComplexAlgebraicRing rfac = new ComplexAlgebraicRing(gen, rt);
231        RingFactory base = (RingFactory) rfac;
232        return new ExtensionFieldBuilder(base);
233    }
234
235
236    /**
237     * String representation of the ideal.
238     * @see java.lang.Object#toString()
239     */
240    @Override
241    public String toString() {
242        StringBuffer s = new StringBuffer(" ");
243        s.append(factory.toString());
244        s.append(" ");
245        return s.toString();
246    }
247
248
249    /**
250     * Get a scripting compatible string representation.
251     * @return script compatible representation for this Element.
252     * @see edu.jas.structure.Element#toScript()
253     */
254    public String toScript() {
255        // Python case
256        StringBuffer s = new StringBuffer(" ");
257        s.append(factory.toScript());
258        s.append(" ");
259        return s.toString();
260    }
261
262}