001/*
002 * $Id: BigQuaternionIntegerTest.java 5731 2017-02-11 11:38:15Z kredel $
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 = b.inverse(); // not entier
239        //d = b.multiply(c);
240        //assertTrue("abs(a)*1/abs(a) = 1", d.isONE());
241        //assertTrue("isEntier(a)", a.isEntier());
242
243        b = a.abs();
244        c = a.conjugate();
245        d = a.multiply(c);
246        assertTrue("isEntier(a)", a.isEntier());
247        assertEquals("abs(a)^2 = a a^", b, d);
248        assertTrue("isEntier(b)", b.isEntier());
249        assertTrue("isEntier(c)", c.isEntier());
250        assertTrue("isEntier(d)", d.isEntier());
251    }
252
253
254    /**
255     * Test multiplication axioms.
256     */
257    public void testMultiplicationAxioms() {
258        a = fac.random(10);
259        b = fac.random(10);
260
261        c = a.multiply(b);
262        d = b.multiply(a);
263        assertFalse("a*b != b*a", c.equals(d));
264
265        assertTrue("isEntier(a)", a.isEntier());
266        assertTrue("isEntier(b)", b.isEntier());
267        assertTrue("isEntier(c)", c.isEntier());
268        assertTrue("isEntier(d)", d.isEntier());
269
270        c = fac.random(10);
271
272        d = a.multiply(b.multiply(c));
273        e = a.multiply(b).multiply(c);
274        assertTrue("a(bc) = (ab)c", e.equals(d));
275        assertTrue("isEntier(c)", c.isEntier());
276        assertTrue("isEntier(d)", d.isEntier());
277        assertTrue("isEntier(e)", e.isEntier());
278    }
279
280
281    /**
282     * Test distributive law.
283     */
284    public void testDistributive() {
285        a = fac.random(20);
286        b = fac.random(20);
287        c = fac.random(20);
288
289        d = a.multiply(b.sum(c));
290        e = a.multiply(b).sum(a.multiply(c));
291        assertEquals("a(b+c) = ab+ac", d, e);
292
293        assertTrue("isEntier(a)", a.isEntier());
294        assertTrue("isEntier(b)", b.isEntier());
295        assertTrue("isEntier(c)", c.isEntier());
296        assertTrue("isEntier(d)", d.isEntier());
297        assertTrue("isEntier(e)", e.isEntier());
298    }
299
300
301    /**
302     * Test divide entier elements.
303     */
304    public void testDivideEntier() {
305        a = new BigQuaternionInteger(fac, "3 i 4 j 5 k 2");
306        assertTrue("a is entier", a.isEntier());
307        //System.out.println("a = " + a);
308
309        b = new BigQuaternionInteger(fac, "-3/2 i -5/2 j -1/2 k -7/2");
310        assertTrue("b is entier", b.isEntier());
311        //System.out.println("b = " + b);
312
313        c = a.multiply(a);
314        //System.out.println("c = " + c); 
315        assertTrue("c is entier", c.isEntier());
316
317        c = b.multiply(b);
318        //System.out.println("c = " + c);
319        assertTrue("c is entier", c.isEntier());
320
321        c = a.multiply(b);
322        //System.out.println("c = " + c);
323        assertTrue("c is entier", c.isEntier());
324
325        c = b.multiply(a);
326        //System.out.println("c = " + c);
327        assertTrue("c is entier", c.isEntier());
328
329        d = a.norm();
330        //System.out.println("norm(a) = " + d);
331        assertTrue("d is entier", d.isEntier());
332
333        d = b.norm();
334        //System.out.println("norm(b) = " + d);
335        assertTrue("d is entier", d.isEntier());
336
337        BigQuaternionInteger ai, bi;
338        ai = new BigQuaternionInteger(fac, a);
339        bi = new BigQuaternionInteger(fac, b);
340        // quotient and remainder
341        //System.out.println("ai = " + ai.toScript());
342        //System.out.println("bi = " + bi.toScript());
343        BigQuaternion[] qr = ai.leftQuotientAndRemainder(bi);
344        c = qr[0];
345        d = qr[1];
346        //System.out.println("q = " + c.toScript());
347        //System.out.println("d = " + d.toScript());
348        assertTrue("c is entier", c.isEntier());
349        assertTrue("d is entier", d.isEntier());
350        //System.out.println("norm(b) = " + b.norm());
351        //System.out.println("norm(r) = " + d.norm());
352        assertEquals("a == b * q + r: ", a, b.multiply(c).sum(d));
353        assertTrue("norm(r) < norm(b): ", d.norm().re.compareTo(b.norm().re) < 0);
354
355        qr = ai.rightQuotientAndRemainder(bi);
356        c = qr[0];
357        d = qr[1];
358        //System.out.println("q = " + c.toScript());
359        //System.out.println("d = " + d.toScript());
360        assertTrue("c is entier", c.isEntier());
361        assertTrue("d is entier", d.isEntier());
362        //System.out.println("norm(b) = " + b.norm());
363        //System.out.println("norm(r) = " + d.norm());
364        assertEquals("a == q * b + r: ", a, c.multiply(b).sum(d));
365        assertTrue("norm(r) < norm(b): ", d.norm().re.compareTo(b.norm().re) < 0);
366    }
367
368
369    /**
370     * Test gcd entier elements.
371     */
372    public void testGcdEntier() {
373        a = fac.random(10);
374        b = fac.random(10);
375        BigQuaternionInteger ai, bi;
376        ai = new BigQuaternionInteger(fac, a);
377        bi = new BigQuaternionInteger(fac, b);
378
379        BigQuaternion g = ai.leftGcd(bi);
380        //System.out.println("g = " + g.toScript());
381        //System.out.println("norm(g) = " + g.norm());
382        assertTrue("g is entier", g.isEntier());
383        BigQuaternion r = ai.leftQuotientAndRemainder(g)[1];
384        //System.out.println("r = " + r.toScript());
385        assertTrue("r == 0: ", r.isZERO());
386        r = bi.leftQuotientAndRemainder(g)[1];
387        //System.out.println("r = " + r.toScript());
388        assertTrue("r == 0: " + r, r.isZERO());
389
390        BigQuaternion h = ai.rightGcd(bi);
391        //System.out.println("h = " + h.toScript());
392        //System.out.println("norm(h) = " + h.norm());
393        assertTrue("h is entier", h.isEntier());
394        r = ai.rightQuotientAndRemainder(h)[1];
395        //System.out.println("r = " + r.toScript());
396        assertTrue("r == 0: ", r.isZERO());
397        r = bi.rightQuotientAndRemainder(h)[1];
398        //System.out.println("r = " + r.toScript());
399        assertTrue("r == 0: ", r.isZERO());
400
401        // round to entier and factor norm
402        a = fac.random(20).roundToLipschitzian();
403        //a = fac.random(20).roundToHurwitzian();
404        //System.out.println("a = " + a.toScript());
405        b = a.norm();
406        //System.out.println("b = " + b.toScript());
407        java.math.BigInteger pp = b.re.floor();
408        //System.out.println("pp = " + pp);
409        long pl = pp.longValue();
410
411        SortedMap<Long, Integer> P = PrimeInteger.factors(pl);
412        //System.out.println("P = " + P);
413        for (Long p : P.keySet()) {
414            c = new BigQuaternion(fac, new BigRational(p));
415            //System.out.println("c = " + c);
416            d = a.leftGcd(c);
417            //System.out.println("d = " + d.toScript());
418            e = d.norm();
419            //System.out.println("e = " + e);
420            assertTrue("norm(gcd) == c: " + c + " : " + e,
421                            c.equals(e) || c.equals(e.power(2)) || c.power(2).equals(e));
422        }
423    }
424
425}