001/*
002 * $Id$
003 */
004
005package edu.jas.arith;
006
007
008import java.util.SortedMap;
009
010import junit.framework.Test;
011import junit.framework.TestCase;
012import junit.framework.TestSuite;
013
014
015/**
016 * BigQuaternionInteger tests with JUnit.
017 * @author Heinz Kredel
018 */
019
020public class BigQuaternionIntegerTest extends TestCase {
021
022
023    /**
024     * main.
025     */
026    public static void main(String[] args) {
027        junit.textui.TestRunner.run(suite());
028    }
029
030
031    /**
032     * Constructs a <CODE>BigQuaternionIntegerTest</CODE> object.
033     * @param name String.
034     */
035    public BigQuaternionIntegerTest(String name) {
036        super(name);
037    }
038
039
040    /**
041     * @return suite.
042     */
043    public static Test suite() {
044        TestSuite suite = new TestSuite(BigQuaternionIntegerTest.class);
045        return suite;
046    }
047
048
049    BigQuaternion a, b, c, d, e, f;
050
051
052    BigQuaternionRing fac;
053
054
055    @Override
056    protected void setUp() {
057        a = b = c = d = e = null;
058        fac = new BigQuaternionRing(true);
059    }
060
061
062    @Override
063    protected void tearDown() {
064        a = b = c = d = e = null;
065        fac = null;
066    }
067
068
069    /**
070     * Test static initialization and constants.
071     */
072    public void testConstants() {
073        a = fac.getZERO();
074        b = fac.getONE();
075        c = b.subtract(b);
076        assertEquals("1-1 = 0", c, a);
077        assertTrue("1-1 = 0", c.isZERO());
078        assertTrue("1 = 1", b.isONE());
079
080        assertTrue("isEntier(0)", a.isEntier());
081        assertTrue("isEntier(1)", b.isEntier());
082        assertTrue("isEntier(c)", c.isEntier());
083    }
084
085
086    /**
087     * Test bitLength.
088     */
089    public void testBitLength() {
090        a = fac.ZERO;
091        b = fac.ONE;
092        c = fac.random(100);
093        //System.out.println("c = " + c);
094        //System.out.println("len(c) = " + c.bitLength());
095
096        assertEquals("len(0) = 12", 12, a.bitLength());
097        assertEquals("len(1) = 13", 13, b.bitLength());
098        assertEquals("len(-1) = 13", 13, b.negate().bitLength());
099        assertTrue("len(random) >= 12", 12 <= c.bitLength());
100
101        d = fac.I;
102        assertEquals("len(i) = 13", 13, d.bitLength());
103        assertEquals("len(-i) = 13", 13, d.negate().bitLength());
104
105        d = fac.J;
106        assertEquals("len(j) = 13", 13, d.bitLength());
107        assertEquals("len(-j) = 13", 13, d.negate().bitLength());
108
109        d = fac.K;
110        assertEquals("len(k) = 13", 13, d.bitLength());
111        assertEquals("len(-k) = 13", 13, d.negate().bitLength());
112    }
113
114
115    /**
116     * Test constructor and toString.
117     */
118    public void testConstructor() {
119        a = new BigQuaternionInteger(fac, "6/8");
120        b = new BigQuaternionInteger(fac, "3/4");
121
122        assertEquals("6/8 = 3/4", a, b);
123        assertFalse("isEntier(a)", a.isEntier());
124        assertFalse("isEntier(b)", b.isEntier());
125
126        a = new BigQuaternionInteger(fac, "3/4 i 4/5 j 1/5 k 2/5");
127        b = new BigQuaternionInteger(fac, "-3/4 i -4/5 j -1/5 k -2/5");
128        assertEquals("3/4 + i 4/5 + j 1/5 + k 2/5", a, b.negate());
129        assertFalse("isEntier(a)", a.isEntier());
130        assertFalse("isEntier(b)", b.isEntier());
131
132        String s = "6/1111111111111111111111111111111111111111111";
133        a = new BigQuaternionInteger(fac, s);
134        String t = a.toString();
135
136        assertFalse("isEntier(a)", a.isEntier());
137        assertEquals("stringConstr = toString", s, t);
138
139        a = new BigQuaternionInteger(fac, 1);
140        b = new BigQuaternionInteger(fac, -1);
141        c = b.sum(a);
142        assertTrue("isEntier(a)", a.isEntier());
143        assertTrue("isEntier(b)", b.isEntier());
144        assertTrue("isEntier(c)", c.isEntier());
145
146        assertTrue("1 = 1", a.isONE());
147        assertEquals("1+(-1) = 0", c, fac.ZERO);
148    }
149
150
151    /**
152     * Test random rationals.
153     */
154    public void testRandom() {
155        a = fac.random(50);
156        b = new BigQuaternionInteger(fac, a.getRe(), a.getIm(), a.getJm(), a.getKm());
157        c = b.subtract(a);
158        assertTrue("isEntier(a)", a.isEntier());
159        assertTrue("isEntier(b)", b.isEntier());
160        assertTrue("isEntier(c)", c.isEntier());
161
162        assertEquals("a-b = 0", fac.ZERO, c);
163
164        d = new BigQuaternionInteger(fac, b);
165        assertEquals("sign(a-a) = 0", 0, b.compareTo(d));
166        assertTrue("isEntier(d)", d.isEntier());
167    }
168
169
170    /**
171     * Test addition.
172     */
173    public void testAddition() {
174        a = fac.random(10);
175        b = a.sum(a);
176        c = b.subtract(a);
177        assertEquals("a+a-a = a", c, a);
178        assertEquals("a+a-a = a", 0, c.compareTo(a));
179
180        assertTrue("isEntier(a)", a.isEntier());
181        assertTrue("isEntier(b)", b.isEntier());
182        assertTrue("isEntier(c)", c.isEntier());
183
184        d = a.sum(fac.ZERO);
185        assertEquals("a+0 = a", d, a);
186
187        d = a.subtract(fac.ZERO);
188        assertEquals("a-0 = a", d, a);
189
190        d = a.subtract(a);
191        assertEquals("a-a = 0", d, fac.ZERO);
192        assertTrue("isEntier(d)", d.isEntier());
193    }
194
195
196    /**
197     * Test multiplication.
198     */
199    public void testMultiplication() {
200        a = fac.random(10);
201        b = a.multiply(a);
202        c = b.leftDivide(a);
203        BigQuaternionInteger bi = new BigQuaternionInteger(fac, b);
204        d = bi.leftDivide(a);
205        //System.out.println("a = " + a);
206        //System.out.println("b = " + b);
207        //System.out.println("c = " + c);
208        //System.out.println("d = " + d);
209        assertTrue("isEntier(a)", a.isEntier());
210        assertTrue("isEntier(b)", b.isEntier());
211        assertTrue("isEntier(c)", c.isEntier());
212        assertTrue("isEntier(d)", d.isEntier());
213
214        //if (! d.equals(a)) {
215        //    e = a.multiply(d);
216        //    System.out.println("e = " + e + ", e==b: " + e.equals(bi));
217        //    e = d.multiply(a);
218        //    System.out.println("e = " + e + ", e==b: " + e.equals(bi));
219        //} 
220        assertEquals("a*a/a = a", d, a); // || !d.isZERO());
221
222        d = a.multiply(fac.ONE);
223        assertEquals("a*1 = a", d, a);
224        d = a.divide(fac.ONE);
225        assertEquals("a/1 = a", d, a);
226
227        //a = fac.random(10);
228        //b = a.inverse(); // not entier
229        //c = a.multiply(b);
230        //assertTrue("a*1/a = 1", c.isONE());
231        //c = b.multiply(a);
232        //assertTrue("1/a*a = 1", c.isONE());
233        //assertTrue("isEntier(a)", a.isEntier());
234        //assertTrue("isEntier(b)", b.isEntier());
235        //assertTrue("isEntier(c)", c.isEntier());
236
237        //b = a.abs();
238        //c = a.norm();
239        //assertEquals("abs() == norm(): " + b, b, c); // wrong
240
241        //c = b.inverse(); // not entier
242        //d = b.multiply(c);
243        //assertTrue("abs(a)*1/abs(a) = 1", d.isONE());
244        //assertTrue("isEntier(a)", a.isEntier());
245
246        b = a.norm();
247        c = a.conjugate();
248        d = a.multiply(c);
249        assertTrue("isEntier(a)", a.isEntier());
250        assertEquals("abs(a)^2 = a a^", b, d);
251        assertTrue("isEntier(b)", b.isEntier());
252        assertTrue("isEntier(c)", c.isEntier());
253        assertTrue("isEntier(d)", d.isEntier());
254    }
255
256
257    /**
258     * Test multiplication axioms.
259     */
260    public void testMultiplicationAxioms() {
261        a = fac.random(10);
262        b = fac.random(10);
263
264        c = a.multiply(b);
265        d = b.multiply(a);
266        if (c.compareTo(d) != 0) {
267            assertFalse("a*b != b*a: " + c + ", " + d, c.equals(d));
268        }
269
270        assertTrue("isEntier(a)", a.isEntier());
271        assertTrue("isEntier(b)", b.isEntier());
272        assertTrue("isEntier(c)", c.isEntier());
273        assertTrue("isEntier(d)", d.isEntier());
274
275        c = fac.random(10);
276
277        d = a.multiply(b.multiply(c));
278        e = a.multiply(b).multiply(c);
279        assertTrue("a(bc) = (ab)c", e.equals(d));
280        assertTrue("isEntier(c)", c.isEntier());
281        assertTrue("isEntier(d)", d.isEntier());
282        assertTrue("isEntier(e)", e.isEntier());
283    }
284
285
286    /**
287     * Test distributive law.
288     */
289    public void testDistributive() {
290        a = fac.random(20);
291        b = fac.random(20);
292        c = fac.random(20);
293
294        d = a.multiply(b.sum(c));
295        e = a.multiply(b).sum(a.multiply(c));
296        assertEquals("a(b+c) = ab+ac", d, e);
297
298        assertTrue("isEntier(a)", a.isEntier());
299        assertTrue("isEntier(b)", b.isEntier());
300        assertTrue("isEntier(c)", c.isEntier());
301        assertTrue("isEntier(d)", d.isEntier());
302        assertTrue("isEntier(e)", e.isEntier());
303    }
304
305
306    /**
307     * Test divide entier elements.
308     */
309    public void testDivideEntier() {
310        a = new BigQuaternionInteger(fac, "3 i 4 j 5 k 2");
311        assertTrue("a is entier", a.isEntier());
312        //System.out.println("a = " + a);
313
314        b = new BigQuaternionInteger(fac, "-3/2 i -5/2 j -1/2 k -7/2");
315        assertTrue("b is entier", b.isEntier());
316        //System.out.println("b = " + b);
317
318        c = a.multiply(a);
319        //System.out.println("c = " + c); 
320        assertTrue("c is entier", c.isEntier());
321
322        c = b.multiply(b);
323        //System.out.println("c = " + c);
324        assertTrue("c is entier", c.isEntier());
325
326        c = a.multiply(b);
327        //System.out.println("c = " + c);
328        assertTrue("c is entier", c.isEntier());
329
330        c = b.multiply(a);
331        //System.out.println("c = " + c);
332        assertTrue("c is entier", c.isEntier());
333
334        d = a.norm();
335        //System.out.println("norm(a) = " + d);
336        assertTrue("d is entier", d.isEntier());
337
338        d = b.norm();
339        //System.out.println("norm(b) = " + d);
340        assertTrue("d is entier", d.isEntier());
341
342        BigQuaternionInteger ai, bi;
343        ai = new BigQuaternionInteger(fac, a);
344        bi = new BigQuaternionInteger(fac, b);
345        // quotient and remainder
346        //System.out.println("ai = " + ai.toScript());
347        //System.out.println("bi = " + bi.toScript());
348        BigQuaternion[] qr = ai.leftQuotientAndRemainder(bi);
349        c = qr[0];
350        d = qr[1];
351        //System.out.println("q = " + c.toScript());
352        //System.out.println("d = " + d.toScript());
353        assertTrue("c is entier", c.isEntier());
354        assertTrue("d is entier", d.isEntier());
355        //System.out.println("norm(b) = " + b.norm());
356        //System.out.println("norm(r) = " + d.norm());
357        assertEquals("a == b * q + r: ", a, b.multiply(c).sum(d));
358        assertTrue("norm(r) < norm(b): ", d.norm().re.compareTo(b.norm().re) < 0);
359
360        qr = ai.rightQuotientAndRemainder(bi);
361        c = qr[0];
362        d = qr[1];
363        //System.out.println("q = " + c.toScript());
364        //System.out.println("d = " + d.toScript());
365        assertTrue("c is entier", c.isEntier());
366        assertTrue("d is entier", d.isEntier());
367        //System.out.println("norm(b) = " + b.norm());
368        //System.out.println("norm(r) = " + d.norm());
369        assertEquals("a == q * b + r: ", a, c.multiply(b).sum(d));
370        assertTrue("norm(r) < norm(b): ", d.norm().re.compareTo(b.norm().re) < 0);
371    }
372
373
374    /**
375     * Test gcd entier elements.
376     */
377    public void testGcdEntier() {
378        a = fac.random(10);
379        b = fac.random(10);
380        BigQuaternionInteger ai, bi;
381        ai = new BigQuaternionInteger(fac, a);
382        bi = new BigQuaternionInteger(fac, b);
383
384        BigQuaternion g = ai.leftGcd(bi);
385        //System.out.println("g = " + g.toScript());
386        //System.out.println("norm(g) = " + g.norm());
387        assertTrue("g is entier", g.isEntier());
388        BigQuaternion r = ai.leftQuotientAndRemainder(g)[1];
389        //System.out.println("r = " + r.toScript());
390        assertTrue("r == 0: ", r.isZERO());
391        r = bi.leftQuotientAndRemainder(g)[1];
392        //System.out.println("r = " + r.toScript());
393        assertTrue("r == 0: " + r, r.isZERO());
394
395        BigQuaternion h = ai.rightGcd(bi);
396        //System.out.println("h = " + h.toScript());
397        //System.out.println("norm(h) = " + h.norm());
398        assertTrue("h is entier", h.isEntier());
399        r = ai.rightQuotientAndRemainder(h)[1];
400        //System.out.println("r = " + r.toScript());
401        assertTrue("r == 0: ", r.isZERO());
402        r = bi.rightQuotientAndRemainder(h)[1];
403        //System.out.println("r = " + r.toScript());
404        assertTrue("r == 0: ", r.isZERO());
405
406        // round to entier and factor norm
407        a = fac.random(20).roundToLipschitzian();
408        //a = fac.random(20).roundToHurwitzian();
409        //System.out.println("a = " + a.toScript());
410        b = a.norm();
411        //System.out.println("b = " + b.toScript());
412        java.math.BigInteger pp = b.re.floor();
413        //System.out.println("pp = " + pp);
414        long pl = pp.longValue();
415
416        SortedMap<Long, Integer> P = PrimeInteger.factors(pl);
417        //System.out.println("P = " + P);
418        for (Long p : P.keySet()) {
419            c = new BigQuaternion(fac, new BigRational(p));
420            //System.out.println("c = " + c);
421            d = a.leftGcd(c);
422            //System.out.println("d = " + d.toScript());
423            e = d.norm();
424            //System.out.println("e = " + e);
425            assertTrue("norm(gcd) == c: " + c + " : " + e,
426                            c.equals(e) || c.equals(e.power(2)) || c.power(2).equals(e));
427        }
428    }
429
430
431    /**
432     * Test random integers for being prime.
433     */
434    public void testPrime() {
435        int n = 0;
436        for (int i = 0; i < 10; i++) {
437            BigQuaternionInteger a = (BigQuaternionInteger) fac.random(10+i);
438            assertTrue("isEntier(a)", a.isEntier());
439
440            boolean p = a.isPrime();
441            //System.out.println(p + " = " + a);
442            assertTrue("isPrime(a)", p || true);
443            if (p) n++;
444        }
445        assertTrue("#isPrime(a)", n >= 0);
446    }
447
448}