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