001/*
002 * $Id: PolyUfdUtilTest.java 5863 2018-07-20 11:13:34Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import edu.jas.arith.BigInteger;
009import edu.jas.arith.BigRational;
010import edu.jas.arith.ModLong;
011import edu.jas.arith.ModLongRing;
012import edu.jas.arith.ModInteger;
013import edu.jas.arith.ModIntegerRing;
014import edu.jas.kern.ComputerThreads;
015import edu.jas.poly.AlgebraicNumberRing;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.poly.PolyUtil;
019import edu.jas.poly.TermOrder;
020import edu.jas.poly.TermOrderByName;
021
022import junit.framework.Test;
023import junit.framework.TestCase;
024import junit.framework.TestSuite;
025
026
027/**
028 * PolyUfdUtil tests with JUnit.
029 * @author Heinz Kredel
030 */
031
032public class PolyUfdUtilTest extends TestCase {
033
034
035    /**
036     * main.
037     */
038    public static void main(String[] args) {
039        junit.textui.TestRunner.run(suite());
040        ComputerThreads.terminate();
041    }
042
043
044    /**
045     * Constructs a <CODE>PolyUtilTest</CODE> object.
046     * @param name String.
047     */
048    public PolyUfdUtilTest(String name) {
049        super(name);
050    }
051
052
053    /**
054     */
055    public static Test suite() {
056        TestSuite suite = new TestSuite(PolyUfdUtilTest.class);
057        return suite;
058    }
059
060
061    TermOrder to = TermOrderByName.INVLEX;
062
063
064    GenPolynomialRing<BigInteger> dfac;
065
066
067    GenPolynomialRing<BigInteger> cfac;
068
069
070    GenPolynomialRing<GenPolynomial<BigInteger>> rfac;
071
072
073    BigInteger ai, bi, ci, di, ei;
074
075
076    GenPolynomial<BigInteger> a, b, c, d, e;
077
078
079    GenPolynomial<GenPolynomial<BigInteger>> ar, br, cr, dr, er;
080
081
082    GenPolynomialRing<BigRational> crfac;
083
084
085    GenPolynomialRing<GenPolynomial<BigRational>> rrfac;
086
087 
088    GenPolynomial<GenPolynomial<BigRational>> arr, brr, crr, drr, err, frr;
089
090
091    int rl = 5;
092
093
094    int kl = 5;
095
096
097    int ll = 5;
098
099
100    int el = 3;
101
102
103    float q = 0.3f;
104
105
106    @Override
107    protected void setUp() {
108        a = b = c = d = e = null;
109        ai = bi = ci = di = ei = null;
110        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), rl, to);
111        cfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), rl - 1, to);
112        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(cfac, 1, to);
113    }
114
115
116    @Override
117    protected void tearDown() {
118        a = b = c = d = e = null;
119        ai = bi = ci = di = ei = null;
120        dfac = null;
121        cfac = null;
122        rfac = null;
123        ComputerThreads.terminate();
124    }
125
126
127    protected static java.math.BigInteger getPrime1() {
128        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
129        for (int i = 1; i < 60; i++) {
130            prime *= 2;
131        }
132        prime -= 93;
133        //prime = 37;
134        //System.out.println("p1 = " + prime);
135        return new java.math.BigInteger("" + prime);
136    }
137
138
139    protected static java.math.BigInteger getPrime2() {
140        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
141        for (int i = 1; i < 30; i++) {
142            prime *= 2;
143        }
144        prime -= 35;
145        //prime = 19;
146        //System.out.println("p1 = " + prime);
147        return new java.math.BigInteger("" + prime);
148    }
149
150
151    /**
152     * Test Kronecker substitution.
153     */
154    public void testKroneckerSubstitution() {
155        for (int i = 0; i < 10; i++) {
156            a = dfac.random(kl, ll * 2, el * 5, q);
157            long d = a.degree() + 1L;
158            //System.out.println("\na        = " + a);
159            //System.out.println("deg(a)+1 = " + d);
160
161            b = PolyUfdUtil.<BigInteger> substituteKronecker(a, d);
162            //System.out.println("b        = " + b);
163
164            c = PolyUfdUtil.<BigInteger> backSubstituteKronecker(dfac, b, d);
165            //System.out.println("c        = " + c);
166            e = a.subtract(c);
167            //System.out.println("e        = " + e);
168            assertTrue("back(subst(a)) = a", e.isZERO());
169        }
170    }
171
172
173    /**
174     * Test algebraic number field.
175     */
176    public void testAlgebraicNumberField() {
177        int deg = 11;
178        // characteristic non zero, small
179        ModLongRing gfp = new ModLongRing(32003);
180        //System.out.println("gfp = " + gfp.toScript());
181        AlgebraicNumberRing<ModLong> gfpq = PolyUfdUtil.<ModLong> algebriacNumberField(gfp, deg);
182        //System.out.println("gfpq = " + gfpq.toScript());
183        assertTrue("gfpq.isField: ", gfpq.isField());
184
185        // characteristic non zero, large
186        ModIntegerRing gfP = new ModIntegerRing(getPrime1());
187        //System.out.println("gfP = " + gfP.toScript());
188        AlgebraicNumberRing<ModInteger> gfPq = PolyUfdUtil.<ModInteger> algebriacNumberField(gfP, deg);
189        //System.out.println("gfPq = " + gfPq.toScript());
190        assertTrue("gfPq.isField: ", gfPq.isField());
191
192        // characteristic zero
193        BigRational q = BigRational.ONE;
194        //System.out.println("q = " + q.toScriptFactory());
195        AlgebraicNumberRing<BigRational> gfqq = PolyUfdUtil.<BigRational> algebriacNumberField(q, deg);
196        //System.out.println("gfqq = " + gfqq.toScript());
197        assertTrue("gfqq.isField: ", gfqq.isField());
198
199        //PolyUfdUtil.<BigRational> ensureFieldProperty(gfqq);
200        //System.out.println("gfqq = " + gfqq);
201        //assertTrue("gfqq.isField: ", gfqq.isField());
202    }
203
204
205    /**
206     * Test recursive dense pseudo division.
207     */
208    public void testRecursivePseudoDivisionDense() {
209        String[] cnames = new String[] { "x" };
210        String[] mnames = new String[] { "t" };
211        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), to, cnames);
212        //GenPolynomialRing<BigRational> rdfac = new GenPolynomialRing<BigRational>(new BigRational(1),dfac);
213        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(dfac, to, mnames);
214        QuotientRing<BigInteger> qfac = new QuotientRing<BigInteger>(dfac);
215        GenPolynomialRing<Quotient<BigInteger>> rqfac = new GenPolynomialRing<Quotient<BigInteger>>(qfac,
216                        rfac);
217        //System.out.println("\ndfac  = " + dfac);
218        //System.out.println("rdfac = " + rdfac);
219        //System.out.println("rfac  = " + rfac);
220        //System.out.println("qfac  = " + qfac);
221        //System.out.println("rqfac = " + rqfac);
222
223        ar = rfac.random(kl, 2 * ll, el + 4, q);
224        //ar = rfac.parse(" ( -2 x^4 + 8 x^3 - 5 x^2 - x + 6  ) t^3 + ( 2 x - 8  ) t^2 - ( 13 x^4 - 13 x^3 + x^2 + 2 x - 13  ) ");
225        br = rfac.random(kl, 2 * ll, el + 2, q);
226        //ar = ar.multiply(br);
227        //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6  ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21  ) ");
228        //System.out.println("ar   = " + ar);
229        //System.out.println("br   = " + br);
230
231        dr = PolyUtil.<BigInteger> recursivePseudoDivide(ar, br);
232        //System.out.println("qr   = " + dr);
233        cr = PolyUtil.<BigInteger> recursiveDensePseudoRemainder(ar, br);
234        //System.out.println("rr   = " + cr);
235
236        //boolean t = PolyUtil.<BigInteger> isRecursivePseudoQuotientRemainder(ar, br, dr, cr);
237        //System.out.println("assertTrue lc^n a = q b + r: " + t);
238        //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true
239
240        GenPolynomial<Quotient<BigInteger>> ap = PolyUfdUtil
241                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, ar);
242        GenPolynomial<Quotient<BigInteger>> bp = PolyUfdUtil
243                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, br);
244        GenPolynomial<Quotient<BigInteger>> cp = PolyUfdUtil
245                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, cr);
246        GenPolynomial<Quotient<BigInteger>> dp = PolyUfdUtil
247                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, dr);
248        //System.out.println("ap  = " + ap);
249        //System.out.println("bp  = " + bp);
250        //System.out.println("cp  = " + cp);
251        ////System.out.println("dp  = " + dp);
252        //System.out.println("dp  = " + dp.monic());
253
254        GenPolynomial<Quotient<BigInteger>> qp = ap.divide(bp);
255        GenPolynomial<Quotient<BigInteger>> rp = ap.remainder(bp);
256        ////System.out.println("qp  = " + qp);
257        //System.out.println("qp  = " + qp.monic());
258        //System.out.println("rp  = " + rp);
259        GenPolynomial<Quotient<BigInteger>> rhs = qp.multiply(bp).sum(rp);
260        //System.out.println("qp bp + rp  = " + rhs);
261
262        assertEquals("ap = qp bp + rp: ", ap, rhs);
263
264        assertEquals("cp = rp: ", rp.monic(), cp.monic());
265        //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) );
266        assertEquals("dp = qp: ", qp.monic(), dp.monic()); // ??
267    }
268
269
270    /**
271     * Test recursive sparse pseudo division.
272     */
273    public void testRecursivePseudoDivisionSparse() {
274        String[] cnames = new String[] { "x" };
275        String[] mnames = new String[] { "t" };
276        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), to, cnames);
277        //GenPolynomialRing<BigRational> rdfac = new GenPolynomialRing<BigRational>(new BigRational(1),dfac);
278        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(dfac, to, mnames);
279        QuotientRing<BigInteger> qfac = new QuotientRing<BigInteger>(dfac);
280        GenPolynomialRing<Quotient<BigInteger>> rqfac = new GenPolynomialRing<Quotient<BigInteger>>(qfac,
281                        rfac);
282        //System.out.println("\ndfac  = " + dfac);
283        //System.out.println("rdfac = " + rdfac);
284        //System.out.println("rfac  = " + rfac);
285        //System.out.println("qfac  = " + qfac);
286        //System.out.println("rqfac = " + rqfac);
287
288        ar = rfac.random(kl, 2 * ll, el + 4, q);
289        //ar = rfac.parse(" ( -2 x^4 + 8 x^3 - 5 x^2 - x + 6  ) t^3 + ( 2 x - 8  ) t^2 - ( 13 x^4 - 13 x^3 + x^2 + 2 x - 13  ) ");
290        br = rfac.random(kl, 2 * ll, el + 2, q);
291        //ar = ar.multiply(br);
292        //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6  ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21  ) ");
293        //System.out.println("ar   = " + ar);
294        //System.out.println("br   = " + br);
295
296        dr = PolyUtil.<BigInteger> recursivePseudoDivide(ar, br);
297        //System.out.println("qr   = " + dr);
298        cr = PolyUtil.<BigInteger> recursiveSparsePseudoRemainder(ar, br);
299        //System.out.println("rr   = " + cr);
300
301        //boolean t = PolyUtil.<BigInteger> isRecursivePseudoQuotientRemainder(ar, br, dr, cr);
302        //System.out.println("assertTrue lc^n a = q b + r: " + t);
303        //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true
304
305        GenPolynomial<Quotient<BigInteger>> ap = PolyUfdUtil
306                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, ar);
307        GenPolynomial<Quotient<BigInteger>> bp = PolyUfdUtil
308                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, br);
309        GenPolynomial<Quotient<BigInteger>> cp = PolyUfdUtil
310                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, cr);
311        GenPolynomial<Quotient<BigInteger>> dp = PolyUfdUtil
312                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, dr);
313        //System.out.println("ap  = " + ap);
314        //System.out.println("bp  = " + bp);
315        //System.out.println("cp  = " + cp);
316        ////System.out.println("dp  = " + dp);
317        //System.out.println("dp  = " + dp.monic());
318
319        GenPolynomial<Quotient<BigInteger>> qp = ap.divide(bp);
320        GenPolynomial<Quotient<BigInteger>> rp = ap.remainder(bp);
321        ////System.out.println("qp  = " + qp);
322        //System.out.println("qp  = " + qp.monic());
323        //System.out.println("rp  = " + rp);
324        GenPolynomial<Quotient<BigInteger>> rhs = qp.multiply(bp).sum(rp);
325        //System.out.println("qp bp + rp  = " + rhs);
326
327        assertEquals("ap = qp bp + rp: ", ap, rhs);
328
329        assertEquals("cp = rp: ", rp.monic(), cp.monic());
330        //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) );
331        assertEquals("dp = qp: ", qp.monic(), dp.monic()); // ??
332    }
333
334
335    /**
336     * Test integer from rational coefficients, recursive.
337     */
338    public void testRecursiveIntegerFromRationalCoefficients() {
339        crfac = new GenPolynomialRing<BigRational>(new BigRational(1), cfac);
340        rrfac = new GenPolynomialRing<GenPolynomial<BigRational>>(crfac, rfac);
341        //System.out.println("\ncfac  = " + cfac);
342        //System.out.println("crfac = " + crfac);
343        //System.out.println("rfac  = " + rfac);
344        //System.out.println("rrfac  = " + rrfac);
345
346        // BigRational
347        arr = rrfac.random(kl*kl, 2 * ll, el + 4, q);
348        arr = arr.sum(arr).multiply(arr); //rrfac.fromInteger(11));
349        //System.out.println("arr   = " + arr);
350
351        // BigInteger
352        ar = PolyUfdUtil.integerFromRationalCoefficients(rfac, arr);
353        //System.out.println("ar   = " + ar);
354
355        crr = PolyUtil.<BigRational> monic(arr);
356        //System.out.println("crr   = " + crr);
357
358        // BigRational
359        err = PolyUfdUtil.<BigRational> fromIntegerCoefficients(rrfac, ar);
360        //System.out.println("err   = " + err);
361        err = PolyUtil.<BigRational> monic(err);
362        //System.out.println("err   = " + err);
363
364        assertEquals("crr != err: ", crr, err);
365    }
366
367}