001/*
002 * $Id$
003 */
004
005package edu.jas.arith;
006
007
008import edu.jas.structure.GcdRingElem;
009import edu.jas.structure.NotInvertibleException;
010
011
012/**
013 * ModInteger class with GcdRingElem interface. Objects of this class are
014 * immutable. The SAC2 static methods are also provided.
015 * @author Heinz Kredel
016 * @see java.math.BigInteger
017 */
018
019public final class ModInteger implements GcdRingElem<ModInteger>, Modular {
020
021
022    /**
023     * ModIntegerRing reference.
024     */
025    public final ModIntegerRing ring;
026
027
028    /**
029     * Value part of the element data structure.
030     */
031    public final java.math.BigInteger val;
032
033
034    /**
035     * The constructor creates a ModInteger object from a ModIntegerRing and a
036     * value part.
037     * @param m ModIntegerRing.
038     * @param a math.BigInteger.
039     */
040    public ModInteger(ModIntegerRing m, java.math.BigInteger a) {
041        ring = m;
042        val = a.mod(ring.modul);
043    }
044
045
046    /**
047     * The constructor creates a ModInteger object from a ModIntegerRing and a
048     * long value part.
049     * @param m ModIntegerRing.
050     * @param a long.
051     */
052    public ModInteger(ModIntegerRing m, long a) {
053        this(m, new java.math.BigInteger(String.valueOf(a)));
054    }
055
056
057    /**
058     * The constructor creates a ModInteger object from a ModIntegerRing and a
059     * String value part.
060     * @param m ModIntegerRing.
061     * @param s String.
062     */
063    public ModInteger(ModIntegerRing m, String s) {
064        this(m, new java.math.BigInteger(s.trim()));
065    }
066
067
068    /**
069     * The constructor creates a 0 ModInteger object from a given
070     * ModIntegerRing.
071     * @param m ModIntegerRing.
072     */
073    public ModInteger(ModIntegerRing m) {
074        this(m, java.math.BigInteger.ZERO);
075    }
076
077
078    /**
079     * Get the value part.
080     * @return val.
081     */
082    public java.math.BigInteger getVal() {
083        return val;
084    }
085
086
087    /**
088     * Get the module part.
089     * @return modul.
090     */
091    public java.math.BigInteger getModul() {
092        return ring.modul;
093    }
094
095
096    /**
097     * Get the corresponding element factory.
098     * @return factory for this Element.
099     * @see edu.jas.structure.Element#factory()
100     */
101    public ModIntegerRing factory() {
102        return ring;
103    }
104
105
106    /**
107     * Get the symmetric value part.
108     * @return val with -modul/2 &le; val &lt; modul/2.
109     */
110    public java.math.BigInteger getSymmetricVal() {
111        if (val.add(val).compareTo(ring.modul) > 0) {
112            // val > m/2 as 2*val > m, make symmetric to 0
113            return val.subtract(ring.modul);
114        }
115        return val;
116    }
117
118
119    /**
120     * Return a BigInteger from this Element.
121     * @return a BigInteger of this.
122     */
123    public BigInteger getInteger() {
124        return new BigInteger(val);
125    }
126
127
128    /**
129     * Return a symmetric BigInteger from this Element.
130     * @return a symmetric BigInteger of this.
131     */
132    public BigInteger getSymmetricInteger() {
133        java.math.BigInteger v = val;
134        if (val.add(val).compareTo(ring.modul) > 0) {
135            // val > m/2 as 2*val > m, make symmetric to 0
136            v = val.subtract(ring.modul);
137        }
138        return new BigInteger(v);
139    }
140
141
142    /**
143     * Clone this.
144     * @see java.lang.Object#clone()
145     */
146    @Override
147    public ModInteger copy() {
148        return new ModInteger(ring, val);
149    }
150
151
152    /**
153     * Is ModInteger number zero.
154     * @return If this is 0 then true is returned, else false.
155     * @see edu.jas.structure.RingElem#isZERO()
156     */
157    public boolean isZERO() {
158        return val.signum() == 0;
159    }
160
161
162    /**
163     * Is ModInteger number one.
164     * @return If this is 1 then true is returned, else false.
165     * @see edu.jas.structure.RingElem#isONE()
166     */
167    public boolean isONE() {
168        return val.equals(java.math.BigInteger.ONE);
169    }
170
171
172    /**
173     * Is ModInteger number a unit.
174     * @return If this is a unit then true is returned, else false.
175     * @see edu.jas.structure.RingElem#isUnit()
176     */
177    public boolean isUnit() {
178        if (isZERO()) {
179            return false;
180        }
181        if (ring.isField()) {
182            return true;
183        }
184        java.math.BigInteger g = ring.modul.gcd(val).abs();
185        return (g.equals(java.math.BigInteger.ONE));
186    }
187
188
189    /**
190     * Get the String representation.
191     * @see java.lang.Object#toString()
192     */
193    @Override
194    public String toString() {
195        return val.toString();
196    }
197
198
199    /**
200     * Get a scripting compatible string representation.
201     * @return script compatible representation for this Element.
202     * @see edu.jas.structure.Element#toScript()
203     */
204    @Override
205    public String toScript() {
206        // Python case
207        return toString();
208    }
209
210
211    /**
212     * Get a scripting compatible string representation of the factory.
213     * @return script compatible representation for this ElemFactory.
214     * @see edu.jas.structure.Element#toScriptFactory()
215     */
216    @Override
217    public String toScriptFactory() {
218        // Python case
219        return factory().toScript();
220    }
221
222
223    /**
224     * ModInteger comparison.
225     * @param b ModInteger.
226     * @return sign(this-b).
227     */
228    @Override
229    public int compareTo(ModInteger b) {
230        java.math.BigInteger v = b.val;
231        if (ring != b.ring) {
232            v = v.mod(ring.modul);
233        }
234        return val.compareTo(v);
235    }
236
237
238    /**
239     * ModInteger comparison.
240     * @param A ModInteger.
241     * @param B ModInteger.
242     * @return sign(this-b).
243     */
244    public static int MICOMP(ModInteger A, ModInteger B) {
245        if (A == null)
246            return -B.signum();
247        return A.compareTo(B);
248    }
249
250
251    /**
252     * Comparison with any other object.
253     * @see java.lang.Object#equals(java.lang.Object)
254     */
255    @Override
256    public boolean equals(Object b) {
257        if (!(b instanceof ModInteger)) {
258            return false;
259        }
260        return (0 == compareTo((ModInteger) b));
261    }
262
263
264    /**
265     * Hash code for this ModInteger.
266     * @see java.lang.Object#hashCode()
267     */
268    @Override
269    public int hashCode() {
270        //return 37 * val.hashCode();
271        return val.hashCode();
272    }
273
274
275    /**
276     * ModInteger absolute value.
277     * @return the absolute value of this.
278     * @see edu.jas.structure.RingElem#abs()
279     */
280    public ModInteger abs() {
281        return new ModInteger(ring, val.abs());
282    }
283
284
285    /**
286     * ModInteger absolute value.
287     * @param A ModInteger.
288     * @return the absolute value of A.
289     */
290    public static ModInteger MIABS(ModInteger A) {
291        if (A == null)
292            return null;
293        return A.abs();
294    }
295
296
297    /**
298     * ModInteger negative.
299     * @see edu.jas.structure.RingElem#negate()
300     * @return -this.
301     */
302    public ModInteger negate() {
303        return new ModInteger(ring, val.negate());
304    }
305
306
307    /**
308     * ModInteger negative.
309     * @param A ModInteger.
310     * @return -A.
311     */
312    public static ModInteger MINEG(ModInteger A) {
313        if (A == null)
314            return null;
315        return A.negate();
316    }
317
318
319    /**
320     * ModInteger signum.
321     * @see edu.jas.structure.RingElem#signum()
322     * @return signum(this).
323     */
324    public int signum() {
325        return val.signum();
326    }
327
328
329    /**
330     * ModInteger signum.
331     * @param A ModInteger
332     * @return signum(A).
333     */
334    public static int MISIGN(ModInteger A) {
335        if (A == null)
336            return 0;
337        return A.signum();
338    }
339
340
341    /**
342     * ModInteger subtraction.
343     * @param S ModInteger.
344     * @return this-S.
345     */
346    public ModInteger subtract(ModInteger S) {
347        return new ModInteger(ring, val.subtract(S.val));
348    }
349
350
351    /**
352     * ModInteger subtraction.
353     * @param A ModInteger.
354     * @param B ModInteger.
355     * @return A-B.
356     */
357    public static ModInteger MIDIF(ModInteger A, ModInteger B) {
358        if (A == null)
359            return B.negate();
360        return A.subtract(B);
361    }
362
363
364    /**
365     * ModInteger divide.
366     * @param S ModInteger.
367     * @return this/S.
368     */
369    public ModInteger divide(ModInteger S) {
370        try {
371            return multiply(S.inverse());
372        } catch (NotInvertibleException e) {
373            try {
374                if (val.remainder(S.val).equals(java.math.BigInteger.ZERO)) {
375                    return new ModInteger(ring, val.divide(S.val));
376                }
377                throw new NotInvertibleException(e);
378            } catch (ArithmeticException a) {
379                throw new NotInvertibleException(a);
380            }
381        }
382    }
383
384
385    /**
386     * ModInteger quotient.
387     * @param A ModInteger.
388     * @param B ModInteger.
389     * @return A/B.
390     */
391    public static ModInteger MIQ(ModInteger A, ModInteger B) {
392        if (A == null)
393            return null;
394        return A.divide(B);
395    }
396
397
398    /**
399     * ModInteger inverse.
400     * @see edu.jas.structure.RingElem#inverse()
401     * @throws NotInvertibleException if the element is not invertible.
402     * @return S with S=1/this if defined.
403     */
404    public ModInteger inverse() /*throws NotInvertibleException*/ {
405        try {
406            return new ModInteger(ring, val.modInverse(ring.modul));
407        } catch (ArithmeticException e) {
408            java.math.BigInteger g = val.gcd(ring.modul);
409            java.math.BigInteger f = ring.modul.divide(g);
410            throw new ModularNotInvertibleException(e, new BigInteger(ring.modul), new BigInteger(g),
411                            new BigInteger(f));
412        }
413    }
414
415
416    /**
417     * ModInteger inverse.
418     * @param A is a non-zero integer.
419     * @see edu.jas.structure.RingElem#inverse()
420     * @return S with S=1/A if defined.
421     */
422    public static ModInteger MIINV(ModInteger A) {
423        if (A == null)
424            return null;
425        return A.inverse();
426    }
427
428
429    /**
430     * ModInteger remainder.
431     * @param S ModInteger.
432     * @return remainder(this,S).
433     */
434    public ModInteger remainder(ModInteger S) {
435        if (S == null || S.isZERO()) {
436            throw new ArithmeticException("division by zero");
437        }
438        if (S.isONE()) {
439            return ring.getZERO();
440        }
441        if (S.isUnit()) {
442            return ring.getZERO();
443        }
444        return new ModInteger(ring, val.remainder(S.val));
445    }
446
447
448    /**
449     * ModInteger remainder.
450     * @param A ModInteger.
451     * @param B ModInteger.
452     * @return A - (A/B)*B.
453     */
454    public static ModInteger MIREM(ModInteger A, ModInteger B) {
455        if (A == null)
456            return null;
457        return A.remainder(B);
458    }
459
460
461    /**
462     * Quotient and remainder by division of this by S.
463     * @param S a modular integer
464     * @return [this/S, this - (this/S)*S].
465     */
466    public ModInteger[] quotientRemainder(ModInteger S) {
467        return new ModInteger[] { divide(S), remainder(S) };
468    }
469
470
471    /**
472     * ModInteger multiply.
473     * @param S ModInteger.
474     * @return this*S.
475     */
476    public ModInteger multiply(ModInteger S) {
477        return new ModInteger(ring, val.multiply(S.val));
478    }
479
480
481    /**
482     * ModInteger product.
483     * @param A ModInteger.
484     * @param B ModInteger.
485     * @return A*B.
486     */
487    public static ModInteger MIPROD(ModInteger A, ModInteger B) {
488        if (A == null)
489            return null;
490        return A.multiply(B);
491    }
492
493
494    /**
495     * ModInteger summation.
496     * @param S ModInteger.
497     * @return this+S.
498     */
499    public ModInteger sum(ModInteger S) {
500        return new ModInteger(ring, val.add(S.val));
501    }
502
503
504    /**
505     * ModInteger summation.
506     * @param A ModInteger.
507     * @param B ModInteger.
508     * @return A+B.
509     */
510    public static ModInteger MISUM(ModInteger A, ModInteger B) {
511        if (A == null)
512            return null;
513        return A.sum(B);
514    }
515
516
517    /**
518     * ModInteger greatest common divisor.
519     * @param S ModInteger.
520     * @return gcd(this,S).
521     */
522    public ModInteger gcd(ModInteger S) {
523        if (S.isZERO()) {
524            return this;
525        }
526        if (isZERO()) {
527            return S;
528        }
529        if (isUnit() || S.isUnit()) {
530            return ring.getONE();
531        }
532        return new ModInteger(ring, val.gcd(S.val));
533    }
534
535
536    /**
537     * ModInteger half extended greatest common divisor.
538     * @param S ModInteger.
539     * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S) for some b.
540     */
541    public ModInteger[] hegcd(ModInteger S) {
542        ModInteger[] ret = new ModInteger[2];
543        ret[0] = null;
544        ret[1] = null;
545        if (S == null || S.isZERO()) {
546            ret[0] = this;
547            ret[1] = this.ring.getONE();
548            return ret;
549        }
550        if (isZERO()) {
551            ret[0] = S;
552            return ret;
553        }
554        //System.out.println("this = " + this + ", S = " + S);
555        java.math.BigInteger[] qr;
556        java.math.BigInteger q = this.val;
557        java.math.BigInteger r = S.val;
558        java.math.BigInteger c1 = BigInteger.ONE.val;
559        java.math.BigInteger d1 = BigInteger.ZERO.val;
560        java.math.BigInteger x1;
561        while (!r.equals(java.math.BigInteger.ZERO)) {
562            qr = q.divideAndRemainder(r);
563            q = qr[0];
564            x1 = c1.subtract(q.multiply(d1));
565            c1 = d1;
566            d1 = x1;
567            q = r;
568            r = qr[1];
569        }
570        //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2);
571        ret[0] = new ModInteger(ring, q);
572        ret[1] = new ModInteger(ring, c1);
573        //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); 
574        return ret;
575    }
576
577
578    /**
579     * ModInteger extended greatest common divisor.
580     * @param S ModInteger.
581     * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
582     */
583    public ModInteger[] egcd(ModInteger S) {
584        ModInteger[] ret = new ModInteger[3];
585        ret[0] = null;
586        ret[1] = null;
587        ret[2] = null;
588        if (S == null || S.isZERO()) {
589            ret[0] = this;
590            return ret;
591        }
592        if (isZERO()) {
593            ret[0] = S;
594            return ret;
595        }
596        if (this.isUnit() || S.isUnit()) {
597            ret[0] = ring.getONE();
598            if (this.isUnit() && S.isUnit()) {
599                //ModInteger half = ring.fromInteger(2).inverse();
600                //ret[1] = this.inverse().multiply(half);
601                //ret[2] = S.inverse().multiply(half);
602                //System.out.println("gcd = " + (ret[1].multiply(this).sum(ret[2].multiply(S))));
603                // (1-1*this)/S
604                ret[1] = ring.getONE();
605                ModInteger x = ret[0].subtract(ret[1].multiply(this));
606                ret[2] = x.divide(S);
607                //System.out.println("gcd, a, b = " + (ret[1]) + ", " + ret[2]);
608                //System.out.println("gcd = " + (ret[1].multiply(this).sum(ret[2].multiply(S))));
609                return ret;
610            }
611            if (this.isUnit()) {
612                // oder inverse(S-1)?
613                ret[1] = this.inverse();
614                ret[2] = ring.getZERO();
615                return ret;
616            }
617            // if ( S.isUnit() ) {
618            // oder inverse(this-1)?
619            ret[1] = ring.getZERO();
620            ret[2] = S.inverse();
621            return ret;
622            //}
623        }
624        //System.out.println("this = " + this + ", S = " + S);
625        java.math.BigInteger[] qr;
626        java.math.BigInteger q = this.val;
627        java.math.BigInteger r = S.val;
628        java.math.BigInteger c1 = BigInteger.ONE.val;
629        java.math.BigInteger d1 = BigInteger.ZERO.val;
630        java.math.BigInteger c2 = BigInteger.ZERO.val;
631        java.math.BigInteger d2 = BigInteger.ONE.val;
632        java.math.BigInteger x1;
633        java.math.BigInteger x2;
634        while (!r.equals(java.math.BigInteger.ZERO)) {
635            qr = q.divideAndRemainder(r);
636            q = qr[0];
637            x1 = c1.subtract(q.multiply(d1));
638            x2 = c2.subtract(q.multiply(d2));
639            c1 = d1;
640            c2 = d2;
641            d1 = x1;
642            d2 = x2;
643            q = r;
644            r = qr[1];
645        }
646        //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2);
647        ret[0] = new ModInteger(ring, q);
648        ret[1] = new ModInteger(ring, c1);
649        ret[2] = new ModInteger(ring, c2);
650        return ret;
651    }
652
653
654    /**
655     * Returns the number of bits in the representation of this ModInteger,
656     * including a sign bit. For positive ModIntegers, this is equivalent to
657     * {@code val.bitLength()}.)
658     * @return number of bits in the representation of this ModInteger,
659     *         including a sign bit.
660     */
661    public long bitLength() {
662        long n = val.bitLength();
663        if (val.signum() < 0) {
664            n++;
665        }
666        n++;
667        return n;
668    }
669
670}