001/*
002 * $Id$
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.SortedMap;
011
012import edu.jas.arith.BigInteger;
013import edu.jas.arith.BigRational;
014import edu.jas.arith.ModInt;
015import edu.jas.arith.ModIntRing;
016import edu.jas.arith.ModInteger;
017import edu.jas.arith.ModIntegerRing;
018import edu.jas.arith.ModLong;
019import edu.jas.arith.ModLongRing;
020import edu.jas.kern.ComputerThreads;
021import edu.jas.poly.AlgebraicNumber;
022import edu.jas.poly.AlgebraicNumberRing;
023import edu.jas.poly.GenPolynomial;
024import edu.jas.poly.GenPolynomialRing;
025import edu.jas.poly.PolyUtil;
026import edu.jas.poly.TermOrder;
027import edu.jas.poly.TermOrderByName;
028import edu.jas.ps.UnivPowerSeries;
029import edu.jas.ps.UnivPowerSeriesRing;
030import edu.jas.structure.Power;
031import edu.jas.vector.GenMatrix;
032import edu.jas.vector.GenMatrixRing;
033import edu.jas.vector.GenVector;
034import edu.jas.vector.LinAlg;
035
036import junit.framework.Test;
037import junit.framework.TestCase;
038import junit.framework.TestSuite;
039
040
041/**
042 * PolyUfdUtil tests with JUnit.
043 * @author Heinz Kredel
044 */
045
046public class PolyUfdUtilTest extends TestCase {
047
048
049    /**
050     * main.
051     */
052    public static void main(String[] args) {
053        junit.textui.TestRunner.run(suite());
054        ComputerThreads.terminate();
055    }
056
057
058    /**
059     * Constructs a <CODE>PolyUtilTest</CODE> object.
060     * @param name String.
061     */
062    public PolyUfdUtilTest(String name) {
063        super(name);
064    }
065
066
067    /**
068     */
069    public static Test suite() {
070        TestSuite suite = new TestSuite(PolyUfdUtilTest.class);
071        return suite;
072    }
073
074
075    TermOrder to = TermOrderByName.INVLEX;
076
077
078    GenPolynomialRing<BigInteger> dfac;
079
080
081    GenPolynomialRing<BigInteger> cfac;
082
083
084    GenPolynomialRing<GenPolynomial<BigInteger>> rfac;
085
086
087    BigInteger ai, bi, ci, di, ei;
088
089
090    GenPolynomial<BigInteger> a, b, c, d, e;
091
092
093    GenPolynomial<GenPolynomial<BigInteger>> ar, br, cr, dr, er;
094
095
096    GenPolynomialRing<BigRational> crfac;
097
098
099    GenPolynomialRing<GenPolynomial<BigRational>> rrfac;
100
101
102    GenPolynomial<GenPolynomial<BigRational>> arr, brr, crr, drr, err, frr;
103
104
105    int rl = 5;
106
107
108    int kl = 5;
109
110
111    int ll = 5;
112
113
114    int el = 3;
115
116
117    float q = 0.3f;
118
119
120    @Override
121    protected void setUp() {
122        a = b = c = d = e = null;
123        ai = bi = ci = di = ei = null;
124        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), rl, to);
125        cfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), rl - 1, to);
126        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(cfac, 1, to);
127    }
128
129
130    @Override
131    protected void tearDown() {
132        a = b = c = d = e = null;
133        ai = bi = ci = di = ei = null;
134        dfac = null;
135        cfac = null;
136        rfac = null;
137        ComputerThreads.terminate();
138    }
139
140
141    protected static java.math.BigInteger getPrime1() {
142        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
143        for (int i = 1; i < 60; i++) {
144            prime *= 2;
145        }
146        prime -= 93;
147        //prime = 37;
148        //System.out.println("p1 = " + prime);
149        return new java.math.BigInteger("" + prime);
150    }
151
152
153    protected static java.math.BigInteger getPrime2() {
154        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
155        for (int i = 1; i < 30; i++) {
156            prime *= 2;
157        }
158        prime -= 35;
159        //prime = 19;
160        //System.out.println("p1 = " + prime);
161        return new java.math.BigInteger("" + prime);
162    }
163
164
165    /**
166     * Test Kronecker substitution.
167     */
168    public void testKroneckerSubstitution() {
169        for (int i = 0; i < 10; i++) {
170            a = dfac.random(kl, ll * 2, el * 5, q);
171            long d = a.degree() + 1L;
172            //System.out.println("\na        = " + a);
173            //System.out.println("deg(a)+1 = " + d);
174
175            b = PolyUfdUtil.<BigInteger> substituteKronecker(a, d);
176            //System.out.println("b        = " + b);
177
178            c = PolyUfdUtil.<BigInteger> backSubstituteKronecker(dfac, b, d);
179            //System.out.println("c        = " + c);
180            e = a.subtract(c);
181            //System.out.println("e        = " + e);
182            assertTrue("back(subst(a)) = a", e.isZERO());
183        }
184    }
185
186
187    /**
188     * Test algebraic number field.
189     */
190    public void testAlgebraicNumberField() {
191        int deg = 11;
192        // characteristic non zero, small
193        ModLongRing gfp = new ModLongRing(32003);
194        //System.out.println("gfp = " + gfp.toScript());
195        AlgebraicNumberRing<ModLong> gfpq = PolyUfdUtil.<ModLong> algebraicNumberField(gfp, deg);
196        //System.out.println("gfpq = " + gfpq.toScript());
197        assertTrue("gfpq.isField: ", gfpq.isField());
198
199        // characteristic non zero, large
200        ModIntegerRing gfP = new ModIntegerRing(getPrime1());
201        //System.out.println("gfP = " + gfP.toScript());
202        AlgebraicNumberRing<ModInteger> gfPq = PolyUfdUtil.<ModInteger> algebraicNumberField(gfP, deg);
203        //System.out.println("gfPq = " + gfPq.toScript());
204        assertTrue("gfPq.isField: ", gfPq.isField());
205
206        // characteristic zero
207        BigRational q = BigRational.ONE;
208        //System.out.println("q = " + q.toScriptFactory());
209        AlgebraicNumberRing<BigRational> gfqq = PolyUfdUtil.<BigRational> algebraicNumberField(q, deg);
210        //System.out.println("gfqq = " + gfqq.toScript());
211        assertTrue("gfqq.isField: ", gfqq.isField());
212
213        //PolyUfdUtil.<BigRational> ensureFieldProperty(gfqq);
214        //System.out.println("gfqq = " + gfqq);
215        //assertTrue("gfqq.isField: ", gfqq.isField());
216    }
217
218
219    /**
220     * Test recursive dense pseudo division.
221     */
222    public void testRecursivePseudoDivisionDense() {
223        String[] cnames = new String[] { "x" };
224        String[] mnames = new String[] { "t" };
225        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), to, cnames);
226        //GenPolynomialRing<BigRational> rdfac = new GenPolynomialRing<BigRational>(new BigRational(1),dfac);
227        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(dfac, to, mnames);
228        QuotientRing<BigInteger> qfac = new QuotientRing<BigInteger>(dfac);
229        GenPolynomialRing<Quotient<BigInteger>> rqfac = new GenPolynomialRing<Quotient<BigInteger>>(qfac,
230                        rfac);
231        //System.out.println("\ndfac  = " + dfac);
232        //System.out.println("rdfac = " + rdfac);
233        //System.out.println("rfac  = " + rfac);
234        //System.out.println("qfac  = " + qfac);
235        //System.out.println("rqfac = " + rqfac);
236
237        ar = rfac.random(kl, 2 * ll, el + 4, q);
238        //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  ) ");
239        br = rfac.random(kl, 2 * ll, el + 2, q);
240        //ar = ar.multiply(br);
241        //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6  ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21  ) ");
242        //System.out.println("ar   = " + ar);
243        //System.out.println("br   = " + br);
244
245        dr = PolyUtil.<BigInteger> recursivePseudoDivide(ar, br);
246        //System.out.println("qr   = " + dr);
247        cr = PolyUtil.<BigInteger> recursiveDensePseudoRemainder(ar, br);
248        //System.out.println("rr   = " + cr);
249
250        //boolean t = PolyUtil.<BigInteger> isRecursivePseudoQuotientRemainder(ar, br, dr, cr);
251        //System.out.println("assertTrue lc^n a = q b + r: " + t);
252        //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true
253
254        GenPolynomial<Quotient<BigInteger>> ap = PolyUfdUtil
255                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, ar);
256        GenPolynomial<Quotient<BigInteger>> bp = PolyUfdUtil
257                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, br);
258        GenPolynomial<Quotient<BigInteger>> cp = PolyUfdUtil
259                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, cr);
260        GenPolynomial<Quotient<BigInteger>> dp = PolyUfdUtil
261                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, dr);
262        //System.out.println("ap  = " + ap);
263        //System.out.println("bp  = " + bp);
264        //System.out.println("cp  = " + cp);
265        ////System.out.println("dp  = " + dp);
266        //System.out.println("dp  = " + dp.monic());
267
268        GenPolynomial<Quotient<BigInteger>> qp = ap.divide(bp);
269        GenPolynomial<Quotient<BigInteger>> rp = ap.remainder(bp);
270        ////System.out.println("qp  = " + qp);
271        //System.out.println("qp  = " + qp.monic());
272        //System.out.println("rp  = " + rp);
273        GenPolynomial<Quotient<BigInteger>> rhs = qp.multiply(bp).sum(rp);
274        //System.out.println("qp bp + rp  = " + rhs);
275
276        assertEquals("ap = qp bp + rp: ", ap, rhs);
277
278        assertEquals("cp = rp: ", rp.monic(), cp.monic());
279        //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) );
280        assertEquals("dp = qp: ", qp.monic(), dp.monic()); // ??
281    }
282
283
284    /**
285     * Test recursive sparse pseudo division.
286     */
287    public void testRecursivePseudoDivisionSparse() {
288        String[] cnames = new String[] { "x" };
289        String[] mnames = new String[] { "t" };
290        dfac = new GenPolynomialRing<BigInteger>(new BigInteger(1), to, cnames);
291        //GenPolynomialRing<BigRational> rdfac = new GenPolynomialRing<BigRational>(new BigRational(1),dfac);
292        rfac = new GenPolynomialRing<GenPolynomial<BigInteger>>(dfac, to, mnames);
293        QuotientRing<BigInteger> qfac = new QuotientRing<BigInteger>(dfac);
294        GenPolynomialRing<Quotient<BigInteger>> rqfac = new GenPolynomialRing<Quotient<BigInteger>>(qfac,
295                        rfac);
296        //System.out.println("\ndfac  = " + dfac);
297        //System.out.println("rdfac = " + rdfac);
298        //System.out.println("rfac  = " + rfac);
299        //System.out.println("qfac  = " + qfac);
300        //System.out.println("rqfac = " + rqfac);
301
302        ar = rfac.random(kl, 2 * ll, el + 4, q);
303        //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  ) ");
304        br = rfac.random(kl, 2 * ll, el + 2, q);
305        //ar = ar.multiply(br);
306        //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6  ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21  ) ");
307        //System.out.println("ar   = " + ar);
308        //System.out.println("br   = " + br);
309
310        dr = PolyUtil.<BigInteger> recursivePseudoDivide(ar, br);
311        //System.out.println("qr   = " + dr);
312        cr = PolyUtil.<BigInteger> recursiveSparsePseudoRemainder(ar, br);
313        //System.out.println("rr   = " + cr);
314
315        //boolean t = PolyUtil.<BigInteger> isRecursivePseudoQuotientRemainder(ar, br, dr, cr);
316        //System.out.println("assertTrue lc^n a = q b + r: " + t);
317        //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true
318
319        GenPolynomial<Quotient<BigInteger>> ap = PolyUfdUtil
320                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, ar);
321        GenPolynomial<Quotient<BigInteger>> bp = PolyUfdUtil
322                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, br);
323        GenPolynomial<Quotient<BigInteger>> cp = PolyUfdUtil
324                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, cr);
325        GenPolynomial<Quotient<BigInteger>> dp = PolyUfdUtil
326                        .<BigInteger> quotientFromIntegralCoefficients(rqfac, dr);
327        //System.out.println("ap  = " + ap);
328        //System.out.println("bp  = " + bp);
329        //System.out.println("cp  = " + cp);
330        ////System.out.println("dp  = " + dp);
331        //System.out.println("dp  = " + dp.monic());
332
333        GenPolynomial<Quotient<BigInteger>> qp = ap.divide(bp);
334        GenPolynomial<Quotient<BigInteger>> rp = ap.remainder(bp);
335        ////System.out.println("qp  = " + qp);
336        //System.out.println("qp  = " + qp.monic());
337        //System.out.println("rp  = " + rp);
338        GenPolynomial<Quotient<BigInteger>> rhs = qp.multiply(bp).sum(rp);
339        //System.out.println("qp bp + rp  = " + rhs);
340
341        assertEquals("ap = qp bp + rp: ", ap, rhs);
342
343        assertEquals("cp = rp: ", rp.monic(), cp.monic());
344        //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) );
345        assertEquals("dp = qp: ", qp.monic(), dp.monic()); // ??
346    }
347
348
349    /**
350     * Test integer from rational coefficients, recursive.
351     */
352    public void testRecursiveIntegerFromRationalCoefficients() {
353        crfac = new GenPolynomialRing<BigRational>(new BigRational(1), cfac);
354        rrfac = new GenPolynomialRing<GenPolynomial<BigRational>>(crfac, rfac);
355        //System.out.println("\ncfac  = " + cfac);
356        //System.out.println("crfac = " + crfac);
357        //System.out.println("rfac  = " + rfac);
358        //System.out.println("rrfac  = " + rrfac);
359
360        // BigRational
361        arr = rrfac.random(kl * kl, 2 * ll, el + 4, q);
362        arr = arr.sum(arr).multiply(arr); //rrfac.fromInteger(11));
363        //System.out.println("arr   = " + arr);
364
365        // BigInteger
366        ar = PolyUfdUtil.integerFromRationalCoefficients(rfac, arr);
367        //System.out.println("ar   = " + ar);
368
369        crr = PolyUtil.<BigRational> monic(arr);
370        //System.out.println("crr   = " + crr);
371
372        // BigRational
373        err = PolyUfdUtil.<BigRational> fromIntegerCoefficients(rrfac, ar);
374        //System.out.println("err   = " + err);
375        err = PolyUtil.<BigRational> monic(err);
376        //System.out.println("err   = " + err);
377
378        assertEquals("crr != err: ", crr, err);
379    }
380
381
382    /**
383     * Test norm over algebraic number field.
384     */
385    public void testNormAlgebraicNumberField() {
386        int deg = 5;
387        // characteristic zero
388        BigRational q = BigRational.ONE;
389        //System.out.println("q = " + q.toScriptFactory());
390        AlgebraicNumberRing<BigRational> gfqq = PolyUfdUtil.<BigRational> algebraicNumberField(q, deg);
391        //System.out.println("gfqq = " + gfqq.toScript());
392        assertTrue("gfqq.isField: ", gfqq.isField());
393
394        GenPolynomialRing<AlgebraicNumber<BigRational>> pafac;
395        pafac = new GenPolynomialRing<AlgebraicNumber<BigRational>>(gfqq, new String[] { "x" },
396                        TermOrderByName.INVLEX);
397        //System.out.println("pafac = " + pafac.toScript());
398
399        GenPolynomial<AlgebraicNumber<BigRational>> P, Q, R;
400        P = pafac.random(2, 4, 3, 0.4f).monic();
401        Q = pafac.random(2, 4, 3, 0.4f).monic();
402        R = P.multiply(Q);
403        //System.out.println("P = " + P);
404        //System.out.println("Q = " + Q);
405        //System.out.println("R = " + R);
406
407        GenPolynomial<BigRational> nP, nQ, nR, nPQ, rem, gcd;
408        nP = PolyUfdUtil.<BigRational> norm(P);
409        nQ = PolyUfdUtil.<BigRational> norm(Q);
410        nR = PolyUfdUtil.<BigRational> norm(R);
411        nPQ = nP.multiply(nQ);
412        //System.out.println("normP  = " + nP);
413        //System.out.println("normQ  = " + nQ);
414        //System.out.println("normR  = " + nR);
415        //System.out.println("normPQ = " + nPQ);
416
417        //System.out.println("normP*normQ = norm(P*Q): " + nPQ.equals(nR) + "\n");
418        if (nPQ.equals(nR)) {
419            assertEquals("normP*normQ == norm(P*Q)", nPQ, nR);
420            return;
421        }
422        rem = nR.remainder(nPQ);
423        //System.out.println("norm(P*Q) mod normP*normQ == 0: " + rem.isZERO());
424        if (rem.isZERO()) {
425            assertTrue("norm(P*Q) mod normP*normQ == 0", rem.isZERO());
426            return;
427        }
428
429        GreatestCommonDivisorAbstract<BigRational> gcdr = GCDFactory.getImplementation(q);
430        gcd = gcdr.gcd(nPQ, nR);
431        //System.out.println("gcd(norm(P*Q), normP*normQ) != 1: " + (!gcd.isONE()));
432        if (!gcd.isONE()) {
433            assertFalse("gcd(norm(P*Q), normP*normQ) != 1", gcd.isONE());
434            return;
435        }
436        // unreachable:        
437        FactorAbstract<BigRational> facr = FactorFactory.getImplementation(q);
438        SortedMap<GenPolynomial<BigRational>, Long> fnPQ = facr.factors(nPQ);
439        System.out.println("fnPQ = " + fnPQ);
440        SortedMap<GenPolynomial<BigRational>, Long> fnR = facr.factors(nR);
441        System.out.println("fnR = " + fnR);
442    }
443
444
445    /**
446     * Test multivariate norm over algebraic number field.
447     */
448    public void testMultiNormAlgebraicNumberField() {
449        int deg = 5;
450        // characteristic zero
451        BigRational q = BigRational.ONE;
452        //System.out.println("q = " + q.toScriptFactory());
453        AlgebraicNumberRing<BigRational> gfqq = PolyUfdUtil.<BigRational> algebraicNumberField(q, deg);
454        //System.out.println("gfqq = " + gfqq.toScript());
455        assertTrue("gfqq.isField: ", gfqq.isField());
456
457        GenPolynomialRing<AlgebraicNumber<BigRational>> pafac;
458        pafac = new GenPolynomialRing<AlgebraicNumber<BigRational>>(gfqq, new String[] { "x", "y" },
459                        TermOrderByName.INVLEX);
460        //System.out.println("pafac = " + pafac.toScript());
461
462        GenPolynomial<AlgebraicNumber<BigRational>> P, Q, R;
463        P = pafac.random(2, 4, 2, 0.2f).monic();
464        Q = pafac.random(2, 4, 2, 0.2f).monic();
465        R = P.multiply(Q);
466        //System.out.println("P = " + P);
467        //System.out.println("Q = " + Q);
468        //System.out.println("R = " + R);
469
470        GenPolynomial<BigRational> nP, nQ, nR, nPQ, rem, gcd;
471        nP = PolyUfdUtil.<BigRational> norm(P);
472        nQ = PolyUfdUtil.<BigRational> norm(Q);
473        nR = PolyUfdUtil.<BigRational> norm(R);
474        nPQ = nP.multiply(nQ);
475        //System.out.println("normP  = " + nP);
476        //System.out.println("normQ  = " + nQ);
477        //System.out.println("normR  = " + nR);
478        //System.out.println("normPQ = " + nPQ);
479
480        //System.out.println("normP*normQ == norm(P*Q): " + nPQ.equals(nR) + "\n");
481        if (nPQ.equals(nR)) {
482            assertEquals("normP*normQ == norm(P*Q)", nPQ, nR);
483            return;
484        }
485
486        rem = nR.remainder(nPQ);
487        //System.out.println("norm(P*Q) mod normP*normQ == 0: " + rem.isZERO());
488        if (rem.isZERO()) {
489            assertTrue("norm(P*Q) mod normP*normQ == 0", rem.isZERO());
490            return;
491        }
492
493        GreatestCommonDivisorAbstract<BigRational> gcdr = GCDFactory.getImplementation(q);
494        gcd = gcdr.gcd(nPQ, nR);
495        //System.out.println("gcd(norm(P*Q), normP*normQ) != 1: " + (!gcd.isONE()));
496        if (!gcd.isONE()) {
497            assertFalse("gcd(norm(P*Q), normP*normQ) != 1", gcd.isONE());
498            return;
499        }
500        // unreachable:        
501        FactorAbstract<BigRational> facr = FactorFactory.getImplementation(q);
502        SortedMap<GenPolynomial<BigRational>, Long> fnPQ = facr.factors(nPQ);
503        System.out.println("fnPQ = " + fnPQ);
504        SortedMap<GenPolynomial<BigRational>, Long> fnR = facr.factors(nR);
505        System.out.println("fnR = " + fnR);
506    }
507
508
509    /**
510     * Q matrix construction for Berlekamp.
511     */
512    public void testQmatix() {
513        int q = 11; //32003; //11;
514        ModIntRing mi = new ModIntRing(q);
515        // for (ModInt s : mi) {
516        //      System.out.print(" " + s + " ");
517        // }
518        // System.out.println("mi = " + mi.toScript());
519        GenPolynomialRing<ModInt> pfac = new GenPolynomialRing<ModInt>(mi, new String[] { "x" });
520        //System.out.println("pfac = " + pfac.toScript());
521        GenPolynomial<ModInt> A = pfac.parse("x^6 - 3 x^5 + x^4 - 3 x^3 - x^2 -3 x + 1");
522        //System.out.println("A = " + A.toScript());
523        int d = (int) A.degree(0);
524        ArrayList<ArrayList<ModInt>> Q = PolyUfdUtil.<ModInt> constructQmatrix(A);
525        //System.out.println("Q = " + Q);
526        int n = Q.size();
527        int m = Q.get(0).size();
528        assertTrue("size(Q) == deg(a): " + Q, n == d);
529        assertTrue("size(Q(0)) == deg(a): " + Q, m == d);
530
531        GenMatrixRing<ModInt> mfac = new GenMatrixRing<ModInt>(mi, n, m);
532        //System.out.println("mfac = " + mfac.toScript());
533        GenMatrix<ModInt> Qm = new GenMatrix<ModInt>(mfac, Q);
534        //System.out.println("Qm = " + Qm);
535        GenMatrix<ModInt> Qm1 = Qm.subtract(mfac.getONE());
536        //System.out.println("Qm1 = " + Qm1);
537
538        LinAlg<ModInt> lu = new LinAlg<ModInt>();
539        List<GenVector<ModInt>> Nsb = lu.nullSpaceBasis(Qm1);
540        //System.out.println("Nsb = " + Nsb);
541        //GenMatrixRing<ModInt> nfac = new GenMatrixRing<ModInt>(mi,k,d);
542        GenMatrix<ModInt> Ns = mfac.fromVectors(Nsb);
543        //System.out.println("Ns = " + Ns);
544        GenMatrix<ModInt> L1 = Ns.negate(); //mfac.getONE().subtract(Ns);
545        //System.out.println("L1 = " + L1);
546        int k = L1.ring.rows;
547        //System.out.println("k = " + k);
548        assertTrue("0 <= k && k < n: " + L1, 0 <= k && k < n);
549
550        // test with random polynomial
551        do {
552            A = pfac.random(10);
553            //System.out.println("A = " + A.toScript());
554        } while (A.isZERO() || A.degree(0) <= 1);
555        d = (int) A.degree(0);
556        Q = PolyUfdUtil.<ModInt> constructQmatrix(A);
557        //System.out.println("Q = " + Q);
558        n = Q.size();
559        m = Q.get(0).size();
560        assertTrue("size(Q) == deg(a): " + Q, n == d);
561        assertTrue("size(Q(0)) == deg(a): " + Q, m == d);
562        ArrayList<ArrayList<ModInt>> Qa = Q;
563
564        mfac = new GenMatrixRing<ModInt>(mi, n, m);
565        //System.out.println("mfac = " + mfac.toScript());
566        Qm = new GenMatrix<ModInt>(mfac, Q);
567        //System.out.println("Qm = " + Qm);
568        Qm1 = Qm.subtract(mfac.getONE());
569        //System.out.println("Qm1 = " + Qm1);
570
571        Nsb = lu.nullSpaceBasis(Qm1);
572        //System.out.println("Nsb = " + Nsb);
573        //GenMatrixRing<ModInt> nfac = new GenMatrixRing<ModInt>(mi,k,d);
574        Ns = mfac.fromVectors(Nsb);
575        //System.out.println("Ns = " + Ns);
576        L1 = Ns.negate(); //mfac.getONE().subtract(Ns);
577        //System.out.println("L1 = " + L1);
578        k = L1.ring.rows;
579        //System.out.println("k = " + k);
580        assertTrue("0 <= k && k < n: " + L1, 0 <= k && k <= n);
581
582        // test with modPower
583        GenPolynomial<ModInt> x = pfac.univariate(0);
584        //System.out.println("x = " + x.toScript());
585        GenPolynomial<ModInt> r = pfac.getONE();
586        //System.out.println("r = " + r.toScript());
587        ArrayList<GenPolynomial<ModInt>> Qp = new ArrayList<GenPolynomial<ModInt>>();
588        Qp.add(r);
589        GenPolynomial<ModInt> pow = Power.<GenPolynomial<ModInt>> modPositivePower(x, q, A);
590        //System.out.println("pow = " + pow.toScript());
591        Qp.add(pow);
592        r = pow;
593        for (int i = 2; i < d; i++) {
594            r = r.multiply(pow).remainder(A);
595            Qp.add(r);
596        }
597        //System.out.println("Qp = " + Qp);
598        assertTrue("deg(r) < deg(A): " + Qp, r.degree(0) <= A.degree(0));
599
600        UnivPowerSeriesRing<ModInt> psfac = new UnivPowerSeriesRing<ModInt>(pfac);
601        //System.out.println("psfac = " + psfac.toScript());
602        ArrayList<ArrayList<ModInt>> Qb = new ArrayList<ArrayList<ModInt>>();
603        for (GenPolynomial<ModInt> p : Qp) {
604            UnivPowerSeries<ModInt> ps = psfac.fromPolynomial(p);
605            //System.out.println("ps = " + ps.toScript());
606            ArrayList<ModInt> pr = new ArrayList<ModInt>();
607            for (int i = 0; i < d; i++) {
608                ModInt c = ps.coefficient(i);
609                pr.add(c);
610            }
611            Qb.add(pr);
612        }
613        //System.out.println("Qb = " + Qb);
614        assertEquals("Qa == Qb: ", Qa, Qb);
615    }
616
617
618    /**
619     * Test search evaluation points.
620     */
621    public void testSearchEvaluationPoints() {
622        //System.out.println("dfac = " + dfac.toScript());
623        crfac = new GenPolynomialRing<BigRational>(new BigRational(1), dfac);
624        //System.out.println("crfac = " + crfac.toScript());
625        for (int i = 0; i < 5; i++) {
626            a = dfac.random(kl, ll * 2, el * 5, q);
627            //System.out.println("a = " + a);
628            EvalPoints<BigInteger> L = PolyUfdUtil.<BigInteger> evaluationPoints(a);
629            //System.out.println("L = " + L);
630            assertFalse("L != (): ", L.evalPoints.isEmpty());
631
632            GenPolynomial<BigRational> ar = crfac.random(kl, ll, el*2, q*1.5f);
633            //System.out.println("ar = " + ar);
634            EvalPoints<BigRational> Lr = PolyUfdUtil.<BigRational> evaluationPoints(ar);
635            //System.out.println("Lr = " + Lr);
636            assertFalse("Lr != (): ", Lr.evalPoints.isEmpty());
637        }
638    }
639
640}