001/*
002 * $Id$
003 */
004
005package edu.jas.arith;
006
007
008import java.io.StringReader;
009import java.util.ArrayList;
010import java.util.List;
011import java.util.SortedMap;
012
013import edu.jas.kern.PrettyPrint;
014import edu.jas.structure.NotInvertibleException;
015
016import junit.framework.Test;
017import junit.framework.TestCase;
018import junit.framework.TestSuite;
019
020
021/**
022 * ModInteger tests with JUnit.
023 * @author Heinz Kredel
024 */
025
026public class ModIntegerTest extends TestCase {
027
028
029    /**
030     * main.
031     */
032    public static void main(String[] args) {
033        junit.textui.TestRunner.run(suite());
034    }
035
036
037    /**
038     * Constructs a <CODE>ModIntegerTest</CODE> object.
039     * @param name String
040     */
041    public ModIntegerTest(String name) {
042        super(name);
043    }
044
045
046    /**
047     */
048    public static Test suite() {
049        TestSuite suite = new TestSuite(ModIntegerTest.class);
050        return suite;
051    }
052
053
054    ModIntegerRing zm, z1, z2;
055
056
057    ModInteger a, b, c, d, e;
058
059
060    @Override
061    protected void setUp() {
062        zm = z1 = z2 = null;
063        a = b = c = d = e = null;
064    }
065
066
067    @Override
068    protected void tearDown() {
069        zm = z1 = z2 = null;
070        a = b = c = d = e = null;
071    }
072
073
074    protected static java.math.BigInteger getPrime1() {
075        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
076        for (int i = 1; i < 60; i++) {
077            prime *= 2;
078        }
079        prime -= 93;
080        //prime = 37;
081        //System.out.println("p1 = " + prime);
082        return new java.math.BigInteger("" + prime);
083    }
084
085
086    protected static java.math.BigInteger getPrime2() {
087        long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390)
088        for (int i = 1; i < 30; i++) {
089            prime *= 2;
090        }
091        prime -= 35;
092        //prime = 19;
093        //System.out.println("p2 = " + prime);
094        return new java.math.BigInteger("" + prime);
095    }
096
097
098    /**
099     * Test static initialization and constants.
100     */
101    public void testConstants() {
102        zm = new ModIntegerRing(5);
103        d = new ModInteger(zm, 11);
104        a = zm.getZERO();
105        b = zm.getONE();
106        c = ModInteger.MIDIF(b, b);
107
108        assertEquals("1-1 = 0", c, a);
109        assertTrue("1-1 = 0", c.isZERO());
110        assertTrue("1 = 1", b.isONE());
111    }
112
113
114    /**
115     * Test bitLength.
116     */
117    public void testBitLength() {
118        zm = new ModIntegerRing(163);
119        a = zm.getZERO();
120        b = zm.getONE();
121        c = zm.random(30);
122        //System.out.println("c = " + c);
123        //System.out.println("len(c) = " + c.bitLength());
124
125        assertEquals("len(0) = 1", 1, a.bitLength());
126        assertEquals("len(1) = 2", 2, b.bitLength());
127        assertEquals("len(-1) = len(mod)", zm.modul.bitLength() + 1, b.negate().bitLength());
128        assertTrue("len(random) >= 1", 1 <= c.bitLength());
129    }
130
131
132    /**
133     * Test constructor and toString.
134     */
135    public void testConstructor() {
136        zm = new ModIntegerRing("5");
137        a = new ModInteger(zm, "64");
138        b = new ModInteger(zm, "34");
139
140        assertEquals("64(5) = 34(5)", a, b);
141
142        zm = new ModIntegerRing("7");
143        a = new ModInteger(zm, "-4");
144        b = new ModInteger(zm, "3");
145
146        assertEquals("-4(7) = 3(7)", a, b);
147
148        String s = "61111111111111111111111111111111111111111111";
149        zm = new ModIntegerRing("10");
150        a = new ModInteger(zm, s);
151        String t = a.toString();
152
153        if (PrettyPrint.isTrue()) {
154            String st = "1";
155            assertEquals("stringConstr = toString", st, t);
156        } else {
157            String st = "1 mod(10)";
158            assertEquals("stringConstr = toString", st, t);
159        }
160
161        zm = new ModIntegerRing(7);
162        a = new ModInteger(zm, 1);
163        b = new ModInteger(zm, -1);
164        c = ModInteger.MISUM(b, a);
165
166        assertTrue("1 = 1", a.isONE());
167        assertTrue("1 = 1", b.isUnit());
168        assertEquals("1+(-1) = 0", c, zm.getZERO());
169
170        zm = new ModIntegerRing(5);
171        a = new ModInteger(zm, 3);
172        b = new ModInteger(zm, 0);
173        c = zm.parse(" 13 ");
174        assertEquals("3(5) = 3(5)", a, c);
175
176        StringReader sr = new StringReader("  13\n w ");
177        c = zm.parse(sr);
178        assertEquals("3(5) = 3(5)", a, c);
179        //System.out.println("c = " + c);
180    }
181
182
183    /**
184     * Test random modular integers.
185     */
186    public void testRandom() {
187        zm = new ModIntegerRing(19);
188        a = zm.random(500);
189        b = a.copy();
190        c = ModInteger.MIDIF(b, a);
191
192        assertEquals("a-b = 0", c, zm.getZERO());
193
194        d = new ModInteger(new ModIntegerRing(b.getModul()), b.getVal());
195        assertEquals("sign(a-a) = 0", 0, b.compareTo(d));
196    }
197
198
199    /**
200     * Test addition.
201     */
202    public void testAddition() {
203        zm = new ModIntegerRing(19);
204
205        a = zm.random(100);
206        b = ModInteger.MISUM(a, a);
207        c = ModInteger.MIDIF(b, a);
208
209        assertEquals("a+a-a = a", c, a);
210        assertEquals("a+a-a = a", 0, ModInteger.MICOMP(c, a));
211
212        d = ModInteger.MISUM(a, zm.getZERO());
213        assertEquals("a+0 = a", d, a);
214        d = ModInteger.MIDIF(a, zm.getZERO());
215        assertEquals("a-0 = a", d, a);
216        d = ModInteger.MIDIF(a, a);
217        assertEquals("a-a = 0", d, zm.getZERO());
218
219    }
220
221
222    /**
223     * Test multiplication.
224     */
225    @SuppressWarnings("unchecked")
226    public void testMultiplication() {
227        zm = new ModIntegerRing(5);
228        d = new ModInteger(zm, 11);
229
230        a = zm.random(100);
231        if (a.isZERO()) {
232            a = d;
233        }
234        b = ModInteger.MIPROD(a, a);
235        c = ModInteger.MIQ(b, a);
236
237        assertEquals("a*a/a = a", c, a);
238        assertEquals("a*a/a = a", 0, c.compareTo(a));
239
240        d = ModInteger.MIPROD(a, zm.getONE());
241        assertEquals("a*1 = a", d, a);
242        d = ModInteger.MIQ(a, zm.getONE());
243        assertEquals("a/1 = a", d, a);
244
245        a = zm.random(100);
246        if (a.isZERO()) {
247            a = d;
248        }
249        b = ModInteger.MIINV(a);
250        c = ModInteger.MIPROD(a, b);
251
252        assertTrue("a*1/a = 1", c.isONE());
253
254        try {
255            a = zm.getZERO().inverse();
256            fail("0 invertible");
257        } catch (NotInvertibleException expected) {
258            // ok
259        }
260
261        zm = new ModIntegerRing(5 * 3);
262        a = new ModInteger(zm, 5);
263        assertFalse("5 !unit mod 15", a.isUnit());
264
265        try {
266            b = a.inverse();
267            fail("5 invertible");
268        } catch (ModularNotInvertibleException expected) {
269            //ok
270            //expected.printStackTrace();
271            assertTrue("f  = 15 ", expected.f.equals(new BigInteger(15)));
272            assertTrue("f1 =  5 ", expected.f1.equals(new BigInteger(5)));
273            assertTrue("f2 =  3 ", expected.f2.equals(new BigInteger(3)));
274            assertTrue("f  =  f1*f2 ", expected.f.equals(expected.f1.multiply(expected.f2)));
275        } catch (NotInvertibleException e) {
276            //e.printStackTrace();
277            fail("wrong exception " + e);
278        }
279    }
280
281
282    /**
283     * Test chinese remainder.
284     */
285    public void testChineseRemainder() {
286        zm = new ModIntegerRing(19 * 13);
287        a = zm.random(9);
288        //System.out.println("a = " + a);
289        z1 = new ModIntegerRing(19);
290        b = new ModInteger(z1, a.getVal().longValue());
291        //System.out.println("b = " + b);
292        z2 = new ModIntegerRing(13);
293        c = new ModInteger(z2, a.getVal().longValue());
294        //System.out.println("c = " + c);
295        d = new ModInteger(z2, 19);
296        d = d.inverse();
297        //System.out.println("d = " + d);
298
299        e = zm.chineseRemainder(b, d, c);
300        //System.out.println("e = " + e);
301
302        assertEquals("cra(a mod 19,a mod 13) = a", a, e);
303
304        java.math.BigInteger p1 = getPrime1();
305        java.math.BigInteger p2 = getPrime2();
306        java.math.BigInteger p1p2 = p1.multiply(p2);
307        //System.out.println("p1p2 = " + p1p2);
308        //System.out.println("prime p1 ? = " + p1.isProbablePrime(66));
309        //System.out.println("prime p2 ? = " + p2.isProbablePrime(33));
310        //System.out.println("prime p1p1 ? = " + p1p2.isProbablePrime(3));
311        zm = new ModIntegerRing(p1p2);
312        z1 = new ModIntegerRing(p1);
313        z2 = new ModIntegerRing(p2);
314
315        for (int i = 0; i < 5; i++) {
316            a = zm.random((59 + 29) / 2); //60+30 );
317            //System.out.println("a = " + a);
318            b = new ModInteger(z1, a.getVal());
319            //System.out.println("b = " + b);
320            c = new ModInteger(z2, a.getVal());
321            //System.out.println("c = " + c);
322            ModInteger di = new ModInteger(z2, p1);
323            d = di.inverse();
324            //System.out.println("d = " + d);
325
326            e = zm.chineseRemainder(b, d, c);
327            //System.out.println("e = " + e);
328
329            assertEquals("cra(a mod p1,a mod p2) = a", a, e);
330        }
331    }
332
333
334    /**
335     * Test chinese remainder of lists.
336     */
337    public void testChineseRemainderLists() {
338        java.math.BigInteger p1 = getPrime1();
339        java.math.BigInteger p2 = getPrime2();
340        java.math.BigInteger p1p2 = p1.multiply(p2);
341        zm = new ModIntegerRing(p1p2);
342        z1 = new ModIntegerRing(p1);
343        z2 = new ModIntegerRing(p2);
344
345        List<ModInteger> L1 = new ArrayList<ModInteger>();
346        List<ModInteger> L2 = new ArrayList<ModInteger>();
347        List<ModInteger> L;
348
349        for (int i = 0; i < 5; i++) {
350            a = zm.random(17);
351            //System.out.println("a = " + a);
352            b = new ModInteger(z1, a.getVal());
353            //System.out.println("b = " + b);
354            c = new ModInteger(z2, a.getVal());
355            //System.out.println("c = " + c);
356            L1.add(b);
357            L2.add(c);
358        }
359        //System.out.println("L1 = " + L1);
360        //System.out.println("L2 = " + L2);
361
362        L = ModIntegerRing.chineseRemainder(z1.getONE(), z2.getONE(), L1, L2);
363        //System.out.println("L = " + L);
364        assertEquals("p1 * p2) = a.modul: ", zm, L.get(0).ring);
365
366        for (ModInteger d : L) {
367            b = new ModInteger(z1, d.getVal());
368            //System.out.println("b = " + b);
369            c = new ModInteger(z2, d.getVal());
370            //System.out.println("c = " + c);
371            assertTrue("cra(a mod p1, a mod p2) = a: ", L1.contains(b));
372            assertTrue("cra(a mod p1, a mod p2) = a: ", L2.contains(c));
373        }
374    }
375
376
377    /**
378     * Test iterator.
379     */
380    public void testIterator() {
381        int m = 5 * 2;
382        zm = new ModIntegerRing(m);
383        ModInteger j = null;
384        for (ModInteger i : zm) {
385            //System.out.println("i = " + i);
386            j = i;
387        }
388        ModInteger end = new ModInteger(zm, m - 1);
389        assertTrue("j == m-1 ", j.equals(end));
390    }
391
392}