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