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