001/*
002 * $Id$
003 */
004
005package edu.jas.application;
006
007
008import java.util.List;
009
010import edu.jas.arith.BigRational;
011import edu.jas.arith.ModLongRing;
012import edu.jas.kern.ComputerThreads;
013import edu.jas.poly.AlgebraicNumber;
014import edu.jas.poly.AlgebraicNumberRing;
015import edu.jas.poly.ComplexRing;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.root.RealAlgebraicNumber;
019import edu.jas.root.RootFactory;
020import edu.jas.structure.Power;
021import edu.jas.structure.RingElem;
022import edu.jas.structure.RingFactory;
023import edu.jas.ufd.Quotient;
024import edu.jas.ufd.QuotientRing;
025import edu.jas.vector.GenMatrix;
026import edu.jas.vector.GenMatrixRing;
027
028import junit.framework.Test;
029import junit.framework.TestCase;
030import junit.framework.TestSuite;
031
032
033/**
034 * ExtensionFieldBuilder tests with JUnit.
035 * @author Heinz Kredel
036 */
037
038public class ExtensionFieldBuilderTest extends TestCase {
039
040
041    /**
042     * main.
043     */
044    public static void main(String[] args) {
045
046        junit.textui.TestRunner.run(suite());
047    }
048
049
050    /**
051     * Constructs a <CODE>ExtensionFieldBuilderTest</CODE> object.
052     * @param name String.
053     */
054    public ExtensionFieldBuilderTest(String name) {
055        super(name);
056    }
057
058
059    /**
060     * suite.
061     */
062    public static Test suite() {
063        TestSuite suite = new TestSuite(ExtensionFieldBuilderTest.class);
064        return suite;
065    }
066
067
068    ExtensionFieldBuilder builder;
069
070
071    @Override
072    protected void setUp() {
073        builder = null;
074    }
075
076
077    @Override
078    protected void tearDown() {
079        builder = null;
080        ComputerThreads.terminate();
081    }
082
083
084    /**
085     * Test construction Q(sqrt(2))(x)(sqrt(x)) by hand.
086     */
087    public void testConstructionF0() {
088        BigRational bf = new BigRational(1);
089        GenPolynomialRing<BigRational> pf = new GenPolynomialRing<BigRational>(bf, new String[] { "w2" });
090        GenPolynomial<BigRational> a = pf.parse("w2^2 - 2");
091        AlgebraicNumberRing<BigRational> af = new AlgebraicNumberRing<BigRational>(a);
092        GenPolynomialRing<AlgebraicNumber<BigRational>> tf = new GenPolynomialRing<AlgebraicNumber<BigRational>>(
093                        af, new String[] { "x" });
094        QuotientRing<AlgebraicNumber<BigRational>> qf = new QuotientRing<AlgebraicNumber<BigRational>>(tf);
095        GenPolynomialRing<Quotient<AlgebraicNumber<BigRational>>> qaf = new GenPolynomialRing<Quotient<AlgebraicNumber<BigRational>>>(
096                        qf, new String[] { "wx" });
097        GenPolynomial<Quotient<AlgebraicNumber<BigRational>>> b = qaf.parse("wx^2 - x");
098        AlgebraicNumberRing<Quotient<AlgebraicNumber<BigRational>>> fac = new AlgebraicNumberRing<Quotient<AlgebraicNumber<BigRational>>>(
099                        b);
100        //System.out.println("fac = " + fac.toScript());
101
102        List<AlgebraicNumber<Quotient<AlgebraicNumber<BigRational>>>> gens = fac.generators();
103        int s = gens.size();
104        //System.out.println("gens    = " + gens);
105        assertTrue("#gens == 4 " + s, s == 4);
106
107        AlgebraicNumber<Quotient<AlgebraicNumber<BigRational>>> elem = fac.random(2);
108        if (elem.isZERO() || elem.isONE()) {
109            elem = gens.get(s - 1).sum(gens.get(s - 2));
110            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
111            elem = elem.multiply(elem);
112        }
113        //System.out.println("elem     = " + elem.toScript());
114        //System.out.println("elem    = " + elem);
115
116        AlgebraicNumber<Quotient<AlgebraicNumber<BigRational>>> inv = elem.inverse();
117        //System.out.println("inv      = " + inv.toScript());
118        //System.out.println("inv     = " + inv);
119
120        AlgebraicNumber<Quotient<AlgebraicNumber<BigRational>>> e = elem.multiply(inv);
121        assertTrue("e / e == 1 " + e, e.isONE());
122    }
123
124
125    /**
126     * Test construction Q(sqrt(2))(x)(sqrt(x)) by extension field builder.
127     */
128    @SuppressWarnings("unchecked")
129    public void testConstructionF1() {
130        builder = ExtensionFieldBuilder.baseField(new BigRational(1));
131        //System.out.println("builder = " + builder.toString());
132
133        RingFactory fac = builder.build();
134        //System.out.println("fac     = " + fac.toScript());
135
136        builder = builder.algebraicExtension("w2", "w2^2 - 2");
137        //System.out.println("builder = " + builder.toString());
138
139        fac = builder.build();
140        //System.out.println("fac     = " + fac.toScript());
141
142        builder = builder.transcendentExtension("x");
143        //System.out.println("builder = " + builder.toString());
144
145        fac = builder.build();
146        //System.out.println("fac     = " + fac.toScript());
147
148        builder = builder.algebraicExtension("wx", "wx^2 - x"); // number of { } resolved
149        //System.out.println("builder = " + builder.toString());
150
151        fac = builder.build();
152        //System.out.println("fac     = " + fac.toScript());
153
154        List<RingElem> gens = fac.generators();
155        int s = gens.size();
156        //System.out.println("gens    = " + gens);
157        assertTrue("#gens == 4 " + s, s == 4);
158
159        RingElem elem = (RingElem) fac.random(2);
160        if (elem.isZERO() || elem.isONE()) {
161            elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2));
162            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
163            elem = (RingElem) elem.multiply(elem);
164        }
165        //System.out.println("elem     = " + elem.toScript());
166        //System.out.println("elem    = " + elem);
167
168        RingElem inv = (RingElem) elem.inverse();
169        //System.out.println("inv      = " + inv.toScript());
170        //System.out.println("inv     = " + inv);
171
172        RingElem a = (RingElem) elem.multiply(inv);
173        assertTrue("e / e == 1 " + a, a.isONE());
174    }
175
176
177    /**
178     * Test construction Q(x)(sqrt(2))(sqrt(x)) by extension field builder.
179     */
180    @SuppressWarnings("unchecked")
181    public void testConstructionF2() {
182        builder = ExtensionFieldBuilder.baseField(new BigRational(1));
183        //System.out.println("builder = " + builder.toString());
184
185        RingFactory fac = builder.build();
186        //System.out.println("fac     = " + fac.toScript());
187
188        builder = builder.transcendentExtension("x");
189        //System.out.println("builder = " + builder.toString());
190
191        fac = builder.build();
192        //System.out.println("fac     = " + fac.toScript());
193        builder = builder.algebraicExtension("w2", "w2^2 - 2");
194        //System.out.println("builder = " + builder.toString());
195
196        fac = builder.build();
197        //System.out.println("fac     = " + fac.toScript());
198
199        builder = builder.algebraicExtension("wx", "wx^2 - x"); // number of { } resolved
200        //System.out.println("builder = " + builder.toString());
201
202        fac = builder.build();
203        //System.out.println("fac     = " + fac.toScript());
204
205        List<RingElem> gens = fac.generators();
206        int s = gens.size();
207        //System.out.println("gens    = " + gens);
208        assertTrue("#gens == 4 " + s, s == 4);
209
210        RingElem elem = (RingElem) fac.random(1);
211        if (elem.isZERO() || elem.isONE()) {
212            elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2));
213            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
214            elem = (RingElem) elem.multiply(elem);
215        }
216        //System.out.println("elem     = " + elem.toScript());
217        //System.out.println("elem    = " + elem);
218
219        RingElem inv = (RingElem) elem.inverse();
220        //System.out.println("inv      = " + inv.toScript());
221        //System.out.println("inv     = " + inv);
222
223        RingElem a = (RingElem) elem.multiply(inv);
224        assertTrue("e / e == 1 " + a, a.isONE());
225    }
226
227
228    /**
229     * Test construction Z_p(sqrt(2))(x)(sqrt(x)) by extension field builder.
230     */
231    @SuppressWarnings("unchecked")
232    public void testConstructionF3() {
233        RingFactory fac = ExtensionFieldBuilder.baseField(new ModLongRing(7))
234                        .algebraicExtension("w2", "w2^2 - 3").transcendentExtension("x")
235                        .algebraicExtension("wx", "wx^7 - x").build();
236        //System.out.println("fac = " + fac.toScript());
237
238        List<RingElem> gens = fac.generators();
239        int s = gens.size();
240        //System.out.println("gens    = " + gens);
241        assertTrue("#gens == 4 " + s, s == 4);
242
243        RingElem elem = (RingElem) fac.random(2);
244        if (elem.isZERO() || elem.isONE()) {
245            elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2));
246            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
247            elem = (RingElem) elem.multiply(elem);
248        }
249        //System.out.println("elem     = " + elem.toScript());
250        //System.out.println("elem    = " + elem);
251
252        RingElem inv = (RingElem) elem.inverse();
253        //System.out.println("inv      = " + inv.toScript());
254        //System.out.println("inv     = " + inv);
255
256        RingElem a = (RingElem) elem.multiply(inv);
257        assertTrue("e / e == 1 " + a, a.isONE());
258    }
259
260
261    /**
262     * Test construction Q(+3rt(3))(+sqrt(+3rt(3)))(+5rt(2)) by extension field
263     * builder.
264     */
265    @SuppressWarnings("unchecked")
266    public void testConstructionR1() {
267        RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1))
268                        .realAlgebraicExtension("q", "q^3 - 3", "[1,2]")
269                        .realAlgebraicExtension("w", "w^2 - q", "[1,2]")
270                        .realAlgebraicExtension("s", "s^5 - 2", "[1,2]").build();
271        //System.out.println("fac = " + fac.toScript());
272
273        List<RingElem> gens = fac.generators();
274        int s = gens.size();
275        //System.out.println("gens    = " + gens);
276        assertTrue("#gens == 4 " + s, s == 4);
277
278        RingElem elem = (RingElem) fac.random(2);
279        if (elem.isZERO() || elem.isONE()) {
280            elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2));
281            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
282            elem = (RingElem) elem.multiply(elem);
283        }
284        //elem = (RingElem)elem.negate();
285        //System.out.println("elem     = " + elem.toScript());
286        //System.out.println("elem    = " + elem);
287        //BigDecimal ed = new BigDecimal(((Rational)elem).getRational());
288        //System.out.println("        ~ " + ed);
289
290        RingElem inv = (RingElem) elem.inverse();
291        //System.out.println("inv      = " + inv.toScript());
292        //System.out.println("inv     = " + inv);
293        //BigDecimal id = new BigDecimal(((Rational)inv).getRational());
294        //System.out.println("        ~ " + id);
295
296        RingElem a = (RingElem) elem.multiply(inv);
297        //System.out.println("a       = " + a);
298        //System.out.println("        ~ " + ed.multiply(id));
299        assertTrue("e / e == 1 " + a, a.isONE());
300    }
301
302
303    /**
304     * Test construction Q(sqrt(-1))(+3rt(i)) by extension field builder.
305     */
306    @SuppressWarnings("unchecked")
307    public void testConstructionC1() {
308        ComplexRing<BigRational> cf = new ComplexRing<BigRational>(new BigRational(1));
309        //System.out.println("cf = " + cf.toScript());
310        RingFactory fac = ExtensionFieldBuilder.baseField(cf)
311                        .complexAlgebraicExtension("w2", "w2^2 + 2", "[-1i0,1i2]")
312                        //.complexAlgebraicExtension("q3", "q3^3 + { w2 }","[-1i0,1i2]") // not possible
313                        .build();
314        //System.out.println("fac = " + fac.toScript());
315
316        List<RingElem> gens = fac.generators();
317        int s = gens.size();
318        //System.out.println("gens    = " + gens);
319        assertTrue("#gens == 3 " + s, s == 3);
320
321        RingElem elem = (RingElem) fac.random(2);
322        if (elem.isZERO() || elem.isONE()) {
323            elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2));
324            //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2));
325            elem = (RingElem) elem.multiply(elem);
326        }
327        //System.out.println("elem     = " + elem.toScript());
328        //System.out.println("elem    = " + elem);
329
330        RingElem inv = (RingElem) elem.inverse();
331        //System.out.println("inv      = " + inv.toScript());
332        //System.out.println("inv     = " + inv);
333
334        RingElem a = (RingElem) elem.multiply(inv);
335        //System.out.println("a       = " + a);
336        assertTrue("e / e == 1 " + a, a.isONE());
337    }
338
339
340    /**
341     * Test construction Q(+3rt(3))(+sqrt(+3rt(3)))(+5rt(2))[y] by extension
342     * field builder and real root calculation.
343     */
344    @SuppressWarnings("unchecked")
345    public void testConstructionR2factory() {
346        RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1))
347                        .realAlgebraicExtension("q", "q^3 - 3", "[1,2]")
348                        .realAlgebraicExtension("w", "w^2 - q", "[1,2]")
349                        .realAlgebraicExtension("s", "s^5 - 2", "[1,2]").build();
350        //System.out.println("fac = " + fac.toScript());
351
352        List<RingElem> gens = fac.generators();
353        int s = gens.size();
354        //System.out.println("gens    = " + gens);
355        assertTrue("#gens == 4 " + s, s == 4);
356
357        GenPolynomialRing pfac = new GenPolynomialRing(fac, new String[] { "y" });
358        GenPolynomial elem = pfac.parse("y^2 - w s");
359        //elem = (RingElem)elem.negate();
360        //System.out.println("elem    = " + elem.toScript());
361        //System.out.println("elem    = " + elem);
362
363        List<RealAlgebraicNumber<BigRational>> roots = RootFactory
364                        .realAlgebraicNumbers((GenPolynomial<BigRational>) elem);
365        //System.out.println("roots   = " + roots);
366        assertTrue("#roots == 2 " + roots, roots.size() == 2);
367        for (RealAlgebraicNumber root : roots) {
368            //BigDecimal id = new BigDecimal(root.getRational());
369            //System.out.println("root    = " + root);
370            //System.out.println("        ~ " + id);
371            RealAlgebraicNumber inv = root.inverse();
372            //System.out.println("inv     = " + inv);
373            //BigDecimal ivd = new BigDecimal(inv.getRational());
374            //System.out.println("        ~ " + ivd);
375
376            RealAlgebraicNumber a = root.multiply(inv);
377            //System.out.println("a       = " + a);
378            //System.out.println("        ~ " + id.multiply(ivd));
379            assertTrue("y / y == 1 " + a, a.isONE());
380        }
381    }
382
383
384    /**
385     * Test construction by extension field builder and multiple algebraic
386     * extension.
387     */
388    @SuppressWarnings("unchecked")
389    public void testConstructionM1() {
390        RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1))
391                        .algebraicExtension("q,w,s", "( q^3 - 3, w^2 - q, s^5 - 2)").build();
392        //System.out.println("fac = " + fac.toScript());
393
394        List<RingElem> gens = fac.generators();
395        int s = gens.size();
396        //System.out.println("gens    = " + gens);
397        assertTrue("#gens == 4 " + s, s == 4);
398
399        GenPolynomialRing pfac = (GenPolynomialRing) ExtensionFieldBuilder.baseField(fac)
400                        .polynomialExtension("y").build();
401        GenPolynomial elem = pfac.parse("y^2 - w s");
402        //System.out.println("elem    = " + elem.toScript());
403        //System.out.println("elem    = " + elem);
404
405        RingElem r = elem.trailingBaseCoefficient();
406        RingElem t = (RingElem) r.inverse();
407        RingElem u = (RingElem) r.multiply(t);
408        //System.out.println("r       = " + r);
409        //System.out.println("t       = " + t);
410        //System.out.println("r*t     = " + u);
411        assertTrue("r*t == 1: ", u.isONE());
412
413        elem = elem.multiply(elem.negate());
414        //System.out.println("elem    = " + elem);
415        elem = Power.positivePower(elem, 3);
416        //System.out.println("elem    = " + elem);
417        assertFalse("elem == 0 " + elem, elem.isZERO());
418    }
419
420
421    /**
422     * Test construction by extension field builder and multiple transcendent
423     * extension.
424     */
425    @SuppressWarnings("unchecked")
426    public void testConstructionM2() {
427        RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1)).algebraicExtension("q,w,s", "")
428                        .build();
429        //System.out.println("fac = " + fac.toScript());
430
431        List<RingElem> gens = fac.generators();
432        int s = gens.size();
433        //System.out.println("gens    = " + gens);
434        assertTrue("#gens == 4 " + s, s == 4);
435
436        GenPolynomialRing pfac = (GenPolynomialRing) ExtensionFieldBuilder.baseField(fac)
437                        .polynomialExtension("y").build();
438        GenPolynomial elem = pfac.parse("y^2 - w s");
439        //System.out.println("elem    = " + elem.toScript());
440        //System.out.println("elem    = " + elem);
441
442        RingElem r = elem.trailingBaseCoefficient();
443        RingElem t = (RingElem) r.inverse();
444        RingElem u = (RingElem) r.multiply(t);
445        //System.out.println("r       = " + r);
446        //System.out.println("t       = " + t);
447        //System.out.println("r*t     = " + u);
448        assertTrue("r*t == 1: ", u.isONE());
449
450        elem = elem.multiply(elem.negate());
451        //System.out.println("elem    = " + elem);
452        elem = Power.positivePower(elem, 3);
453        //System.out.println("elem    = " + elem);
454        assertFalse("elem == 0 " + elem, elem.isZERO());
455    }
456
457
458    /**
459     * Test construction of matrix extensions.
460     */
461    @SuppressWarnings("unchecked")
462    public void testConstructionMat() {
463        RingFactory fac = ExtensionFieldBuilder.baseField(BigRational.ONE).transcendentExtension("a").build();
464        //System.out.println("fac = " + fac.toScript());
465
466        List<RingElem> gens = fac.generators();
467        int s = gens.size();
468        //System.out.println("gens    = " + gens);
469        assertTrue("#gens == 2 " + s, s == 2);
470
471        GenMatrixRing mfac = (GenMatrixRing) ExtensionFieldBuilder.baseField(fac).matrixExtension(3).build();
472        //System.out.println("mfac = " + mfac.toScript());
473
474        List<RingElem> mgens = mfac.generators();
475        s = mgens.size();
476        //System.out.println("mgens(1) = " + mgens.get(1));
477        assertTrue("#gens == 9*2 " + s, s == 18);
478
479        GenMatrix elem = mfac.parse("[ [1,a,2], [0,1,1], [-1,1,1] ]");
480        //System.out.println("elem    = " + elem);
481
482        GenMatrix elemt = elem.transpose();
483        //System.out.println("elem**t = " + elemt);
484        elem = elem.multiply(elemt);
485        //System.out.println("elem    = " + elem);
486        GenMatrix elemp = (GenMatrix) elem.power(3);
487        //System.out.println("elem**3 = " + elemp);
488        GenMatrix elemi = elem.inverse();
489        //System.out.println("elem^-1 = " + elemi);
490        GenMatrix mat = elem.multiply(elemi);
491        //System.out.println("mat     = " + mat);
492        assertTrue("elem*elem^-1 == 1 " + mat, mat.isONE());
493    }
494
495}