001    /*
002     * $Id: BigRational.java 3652 2011-06-02 18:17:04Z kredel $
003     */
004    
005    package edu.jas.arith;
006    
007    
008    import java.io.Reader;
009    import java.math.BigInteger;
010    import java.util.ArrayList;
011    import java.util.Collections;
012    import java.util.HashSet;
013    import java.util.Iterator;
014    import java.util.List;
015    import java.util.Random;
016    import java.util.Set;
017    
018    import edu.jas.kern.StringUtil;
019    import edu.jas.kern.Scripting;
020    import edu.jas.structure.GcdRingElem;
021    import edu.jas.structure.Power;
022    import edu.jas.structure.RingFactory;
023    
024    
025    /**
026     * Immutable arbitrary-precision rational numbers. BigRational class based on
027     * BigInteger implementing the RingElem interface and with the familiar SAC
028     * static method names. BigInteger is from java.math in the implementation.
029     * @author Heinz Kredel
030     */
031    
032    public final class BigRational implements GcdRingElem<BigRational>, RingFactory<BigRational>, Rational,
033            Iterable<BigRational> {
034    
035    
036        /**
037         * Numerator part of the data structure.
038         */
039        protected final BigInteger num;
040    
041    
042        /**
043         * Denominator part of the data structure.
044         */
045        protected final BigInteger den;
046    
047    
048        /* from history: */
049        private final static BigInteger IZERO = BigInteger.ZERO;
050    
051    
052        private final static BigInteger IONE = BigInteger.ONE;
053    
054    
055        /**
056         * The Constant 0.
057         */
058        public final static BigRational ZERO = new BigRational(BigInteger.ZERO);
059    
060    
061        /**
062         * The Constant 1.
063         */
064        public final static BigRational ONE = new BigRational(BigInteger.ONE);
065    
066    
067        private final static Random random = new Random();
068    
069    
070        /**
071         * Constructor for a BigRational from math.BigIntegers.
072         * @param n math.BigInteger.
073         * @param d math.BigInteger.
074         */
075        protected BigRational(BigInteger n, BigInteger d) {
076            // assert gcd(n,d) == 1
077            num = n;
078            den = d;
079        }
080    
081    
082        /**
083         * Constructor for a BigRational from math.BigIntegers.
084         * @param n math.BigInteger.
085         */
086        public BigRational(BigInteger n) {
087            num = n;
088            den = IONE; // be aware of static initialization order
089            //den = BigInteger.ONE;
090        }
091    
092    
093        /**
094         * Constructor for a BigRational from jas.arith.BigIntegers.
095         * @param n edu.jas.arith.BigInteger.
096         */
097        public BigRational(edu.jas.arith.BigInteger n) {
098            this(n.getVal());
099        }
100    
101    
102        /**
103         * Constructor for a BigRational from longs.
104         * @param n long.
105         * @param d long.
106         */
107        public BigRational(long n, long d) {
108            BigInteger nu = BigInteger.valueOf(n);
109            BigInteger de = BigInteger.valueOf(d);
110            BigRational r = RNRED(nu, de);
111            num = r.num;
112            den = r.den;
113        }
114    
115    
116        /**
117         * Constructor for a BigRational from longs.
118         * @param n long.
119         */
120        public BigRational(long n) {
121            num = BigInteger.valueOf(n);
122            den = IONE;
123        }
124    
125    
126        /**
127         * Constructor for a BigRational with no arguments.
128         */
129        public BigRational() {
130            num = IZERO;
131            den = IONE;
132        }
133    
134    
135        /**
136         * Constructor for a BigRational from String.
137         * @param s String.
138         * @throws NumberFormatException
139         */
140        public BigRational(String s) throws NumberFormatException {
141            if (s == null) {
142                num = IZERO;
143                den = IONE;
144                return;
145            }
146            if (s.length() == 0) {
147                num = IZERO;
148                den = IONE;
149                return;
150            }
151            BigInteger n;
152            BigInteger d;
153            s = s.trim();
154            int i = s.indexOf('/');
155            if (i < 0) {
156                i = s.indexOf('.');
157                if (i < 0) {
158                    num = new BigInteger(s);
159                    den = BigInteger.ONE;
160                    return;
161                }
162                if (s.charAt(0) == '-') { // case -0.11111
163                    n = new BigInteger(s.substring(1, i));
164                } else {
165                    n = new BigInteger(s.substring(0, i));
166                }
167                BigRational r = new BigRational(n);
168                d = new BigInteger(s.substring(i + 1, s.length()));
169                int j = s.length() - i - 1;
170                //System.out.println("j = " + j);
171                //System.out.println("n = " + n);
172                //System.out.println("d = " + d);
173                BigRational z = new BigRational(1, 10);
174                z = Power.<BigRational> positivePower(z, j);
175                BigRational f = new BigRational(d);
176                f = f.multiply(z);
177                r = r.sum(f);
178                if (s.charAt(0) == '-') {
179                    num = r.num.negate();
180                } else {
181                    num = r.num;
182                }
183                den = r.den;
184            } else {
185                n = new BigInteger(s.substring(0, i));
186                d = new BigInteger(s.substring(i + 1, s.length()));
187                BigRational r = RNRED(n, d);
188                num = r.num;
189                den = r.den;
190                return;
191            }
192        }
193    
194    
195        /**
196         * Get the corresponding element factory.
197         * @return factory for this Element.
198         * @see edu.jas.structure.Element#factory()
199         */
200        public BigRational factory() {
201            return this;
202        }
203    
204    
205        /**
206         * Get a list of the generating elements.
207         * @return list of generators for the algebraic structure.
208         * @see edu.jas.structure.ElemFactory#generators()
209         */
210        public List<BigRational> generators() {
211            List<BigRational> g = new ArrayList<BigRational>(1);
212            g.add(getONE());
213            return g;
214        }
215    
216    
217        /**
218         * Is this structure finite or infinite.
219         * @return true if this structure is finite, else false.
220         * @see edu.jas.structure.ElemFactory#isFinite()
221         */
222        public boolean isFinite() {
223            return false;
224        }
225    
226    
227        /**
228         * Clone this.
229         * @see java.lang.Object#clone()
230         */
231        @Override
232        public BigRational clone() {
233            return new BigRational(num, den);
234        }
235    
236    
237        /**
238         * Copy BigRational element c.
239         * @param c BigRational.
240         * @return a copy of c.
241         */
242        public BigRational copy(BigRational c) {
243            return new BigRational(c.num, c.den);
244        }
245    
246    
247        /**
248         * Return a BigRational approximation of this Element.
249         * @return a BigRational approximation of this.
250         * @see edu.jas.arith.Rational#getRational()
251         */
252        public BigRational getRational() {
253            return this;
254        }
255    
256    
257        /**
258         * Get the numerator.
259         * @return num.
260         */
261        public BigInteger numerator() {
262            return num;
263        }
264    
265    
266        /**
267         * Get the denominator.
268         * @return den.
269         */
270        public BigInteger denominator() {
271            return den;
272        }
273    
274    
275        /**
276         * Get the string representation.
277         * @see java.lang.Object#toString()
278         */
279        @Override
280        public String toString() {
281            StringBuffer s = new StringBuffer();
282            s.append(num);
283            if (!den.equals(BigInteger.ONE)) {
284                s.append("/").append(den);
285            }
286            return s.toString();
287        }
288    
289    
290        /**
291         * Get the decimal string representation with given precision.
292         * @param n precission.
293         * @return decimal approximation.
294         */
295        public String toString(int n) {
296            java.math.MathContext mc = new java.math.MathContext(n);
297            BigDecimal d = new BigDecimal(this, mc);
298            return d.toString();
299        }
300    
301    
302        /**
303         * Get a scripting compatible string representation.
304         * @return script compatible representation for this Element.
305         * @see edu.jas.structure.Element#toScript()
306         */
307        //JAVA6only: @Override
308        public String toScript() {
309            // Python case: (num,den) or num 
310            // Ruby case: num/den or num 
311            StringBuffer s = new StringBuffer();
312            if (den.equals(BigInteger.ONE)) {
313                s.append(num.toString());
314                return s.toString();
315            }
316            switch (Scripting.getLang() ) {
317            case Python:
318                s.append("(");
319                s.append(num.toString());
320                s.append(",");
321                s.append(den.toString());
322                s.append(")");
323                break;
324            case Ruby:
325            default:
326                s.append(num.toString());
327                s.append("/");
328                s.append(den.toString());
329            }
330            return s.toString();
331        }
332    
333    
334        /**
335         * Get a scripting compatible string representation of the factory.
336         * @return script compatible representation for this ElemFactory.
337         * @see edu.jas.structure.Element#toScriptFactory()
338         */
339        //JAVA6only: @Override
340        public String toScriptFactory() {
341            // Python case
342            return "QQ()";
343        }
344    
345    
346        /**
347         * Get the zero element.
348         * @return 0 as BigRational.
349         */
350        public BigRational getZERO() {
351            return ZERO;
352        }
353    
354    
355        /**
356         * Get the one element.
357         * @return 1 as BigRational.
358         */
359        public BigRational getONE() {
360            return ONE;
361        }
362    
363    
364        /**
365         * Query if this ring is commutative.
366         * @return true.
367         */
368        public boolean isCommutative() {
369            return true;
370        }
371    
372    
373        /**
374         * Query if this ring is associative.
375         * @return true.
376         */
377        public boolean isAssociative() {
378            return true;
379        }
380    
381    
382        /**
383         * Query if this ring is a field.
384         * @return true.
385         */
386        public boolean isField() {
387            return true;
388        }
389    
390    
391        /**
392         * Characteristic of this ring.
393         * @return characteristic of this ring.
394         */
395        public java.math.BigInteger characteristic() {
396            return java.math.BigInteger.ZERO;
397        }
398    
399    
400        /**
401         * Get a BigRational element from a math.BigInteger.
402         * @param a math.BigInteger.
403         * @return BigRational from a.
404         */
405        public BigRational fromInteger(BigInteger a) {
406            return new BigRational(a);
407        }
408    
409    
410        /**
411         * Get a BigRational element from a math.BigInteger.
412         * @param a math.BigInteger.
413         * @return BigRational from a.
414         */
415        public static BigRational valueOf(BigInteger a) {
416            return new BigRational(a);
417        }
418    
419    
420        /**
421         * Get a BigRational element from a long.
422         * @param a long.
423         * @return BigRational from a.
424         */
425        public BigRational fromInteger(long a) {
426            return new BigRational(a);
427        }
428    
429    
430        /**
431         * Get a BigRational element from a long.
432         * @param a long.
433         * @return BigRational from a.
434         */
435        public static BigRational valueOf(long a) {
436            return new BigRational(a);
437        }
438    
439    
440        /**
441         * Is BigRational zero.
442         * @return If this is 0 then true is returned, else false.
443         * @see edu.jas.structure.RingElem#isZERO()
444         */
445        public boolean isZERO() {
446            return num.equals(BigInteger.ZERO);
447        }
448    
449    
450        /**
451         * Is BigRational one.
452         * @return If this is 1 then true is returned, else false.
453         * @see edu.jas.structure.RingElem#isONE()
454         */
455        public boolean isONE() {
456            return num.equals(den);
457        }
458    
459    
460        /**
461         * Is BigRational unit.
462         * @return If this is a unit then true is returned, else false.
463         * @see edu.jas.structure.RingElem#isUnit()
464         */
465        public boolean isUnit() {
466            return (!isZERO());
467        }
468    
469    
470        /**
471         * Comparison with any other object.
472         * @see java.lang.Object#equals(java.lang.Object)
473         */
474        @Override
475        public boolean equals(Object b) {
476            if (!(b instanceof BigRational)) {
477                return false;
478            }
479            BigRational br = (BigRational) b;
480            return num.equals(br.num) && den.equals(br.den);
481        }
482    
483    
484        /**
485         * Hash code for this BigRational.
486         * @see java.lang.Object#hashCode()
487         */
488        @Override
489        public int hashCode() {
490            return 37 * num.hashCode() + den.hashCode();
491        }
492    
493    
494        /**
495         * Rational number reduction to lowest terms.
496         * @param n BigInteger.
497         * @param d BigInteger.
498         * @return a/b ~ n/d, gcd(a,b) = 1, b > 0.
499         */
500        public static BigRational RNRED(BigInteger n, BigInteger d) {
501            BigInteger num;
502            BigInteger den;
503            if (n.equals(IZERO)) {
504                num = n;
505                den = IONE;
506                return new BigRational(num, den);
507            }
508            BigInteger C = n.gcd(d);
509            num = n.divide(C);
510            den = d.divide(C);
511            if (den.signum() < 0) {
512                num = num.negate();
513                den = den.negate();
514            }
515            return new BigRational(num, den);
516        }
517    
518    
519        /**
520         * Rational number reduction to lowest terms.
521         * @param n BigInteger.
522         * @param d BigInteger.
523         * @return a/b ~ n/d, gcd(a,b) = 1, b > 0.
524         */
525        public static BigRational reduction(BigInteger n, BigInteger d) {
526            return RNRED(n, d);
527        }
528    
529    
530        /**
531         * Rational number absolute value.
532         * @return the absolute value of this.
533         * @see edu.jas.structure.RingElem#abs()
534         */
535        public BigRational abs() {
536            if (this.signum() >= 0) {
537                return this;
538            }
539            return this.negate();
540        }
541    
542    
543        /**
544         * Rational number absolute value.
545         * @param R is a rational number.
546         * @return the absolute value of R.
547         */
548        public static BigRational RNABS(BigRational R) {
549            if (R == null)
550                return null;
551            return R.abs();
552        }
553    
554    
555        /**
556         * Rational number comparison.
557         * @param S BigRational.
558         * @return SIGN(this-S).
559         */
560        //JAVA6only: @Override
561        public int compareTo(BigRational S) {
562            BigInteger J2Y;
563            BigInteger J3Y;
564            BigInteger R1;
565            BigInteger R2;
566            BigInteger S1;
567            BigInteger S2;
568            int J1Y;
569            int SL;
570            int TL;
571            int RL;
572            if (this.equals(ZERO)) {
573                return -S.signum();
574            }
575            if (S.equals(ZERO)) {
576                return this.signum();
577            }
578            R1 = num; //this.numerator(); 
579            R2 = den; //this.denominator();
580            S1 = S.num;
581            S2 = S.den;
582            RL = R1.signum();
583            SL = S1.signum();
584            J1Y = (RL - SL);
585            TL = (J1Y / 2);
586            if (TL != 0) {
587                return TL;
588            }
589            J3Y = R1.multiply(S2);
590            J2Y = R2.multiply(S1);
591            TL = J3Y.compareTo(J2Y);
592            return TL;
593        }
594    
595    
596        /**
597         * Rational number comparison.
598         * @param R BigRational.
599         * @param S BigRational.
600         * @return SIGN(R-S).
601         */
602        public static int RNCOMP(BigRational R, BigRational S) {
603            if (R == null)
604                return Integer.MAX_VALUE;
605            return R.compareTo(S);
606        }
607    
608    
609        /**
610         * Rational number denominator.
611         * @param R BigRational.
612         * @return R.denominator().
613         */
614        public static BigInteger RNDEN(BigRational R) {
615            if (R == null)
616                return null;
617            return R.den;
618        }
619    
620    
621        /**
622         * Rational number difference.
623         * @param S BigRational.
624         * @return this-S.
625         */
626        public BigRational subtract(BigRational S) {
627            return this.sum(S.negate());
628        }
629    
630    
631        /**
632         * Rational number difference.
633         * @param R BigRational.
634         * @param S BigRational.
635         * @return R-S.
636         */
637        public static BigRational RNDIF(BigRational R, BigRational S) {
638            if (R == null)
639                return S.negate();
640            return R.subtract(S);
641        }
642    
643    
644        /**
645         * Rational number decimal write. R is a rational number. n is a
646         * non-negative integer. R is approximated by a decimal fraction D with n
647         * decimal digits following the decimal point and D is written in the output
648         * stream. The inaccuracy of the approximation is at most (1/2)*10**-n.
649         * @param R
650         * @param NL
651         */
652        // If ABS(D) is greater than ABS(R) then the last digit is
653        // followed by a minus sign, if ABS(D) is less than ABS(R) then by a
654        // plus sign. 
655        public static void RNDWR(BigRational R, int NL) {
656            //BigInteger num = R.num;
657            //BigInteger den = R.den;
658            java.math.MathContext mc = new java.math.MathContext(NL);
659            BigDecimal d = new BigDecimal(R, mc);
660            System.out.print(d.toString());
661            return;
662        }
663    
664    
665        /**
666         * Rational number from integer.
667         * @param A BigInteger.
668         * @return A/1.
669         */
670        public static BigRational RNINT(BigInteger A) {
671            return new BigRational(A);
672        }
673    
674    
675        /**
676         * Rational number inverse.
677         * @return 1/this.
678         * @see edu.jas.structure.RingElem#inverse()
679         */
680        public BigRational inverse() {
681            BigInteger R1 = num;
682            BigInteger R2 = den;
683            BigInteger S1;
684            BigInteger S2;
685            if (R1.signum() >= 0) {
686                S1 = R2;
687                S2 = R1;
688            } else {
689                S1 = R2.negate();
690                S2 = R1.negate();
691            }
692            return new BigRational(S1, S2);
693        }
694    
695    
696        /**
697         * Rational number inverse.
698         * @param R BigRational.
699         * @return 1/R.
700         */
701        public static BigRational RNINV(BigRational R) {
702            if (R == null)
703                return null;
704            return R.inverse();
705        }
706    
707    
708        /**
709         * Rational number negative.
710         * @return -this.
711         * @see edu.jas.structure.RingElem#negate()
712         */
713        public BigRational negate() {
714            BigInteger n = num.negate();
715            return new BigRational(n, den);
716        }
717    
718    
719        /**
720         * Rational number negative.
721         * @param R BigRational.
722         * @return -R.
723         */
724        public static BigRational RNNEG(BigRational R) {
725            if (R == null)
726                return null;
727            return R.negate();
728        }
729    
730    
731        /**
732         * Rational number numerator.
733         * @param R BigRational.
734         * @return R.numerator().
735         */
736        public static BigInteger RNNUM(BigRational R) {
737            if (R == null)
738                return null;
739            return R.num;
740        }
741    
742    
743        /**
744         * Rational number product.
745         * @param S BigRational.
746         * @return this*S.
747         */
748        public BigRational multiply(BigRational S) {
749            BigInteger D1 = null;
750            BigInteger D2 = null;
751            BigInteger R1 = null;
752            BigInteger R2 = null;
753            BigInteger RB1 = null;
754            BigInteger RB2 = null;
755            BigInteger S1 = null;
756            BigInteger S2 = null;
757            BigInteger SB1 = null;
758            BigInteger SB2 = null;
759            BigRational T;
760            BigInteger T1;
761            BigInteger T2;
762            if (this.equals(ZERO) || S.equals(ZERO)) {
763                T = ZERO;
764                return T;
765            }
766            R1 = num; //this.numerator(); 
767            R2 = den; //this.denominator();
768            S1 = S.num;
769            S2 = S.den;
770            if (R2.equals(IONE) && S2.equals(IONE)) {
771                T1 = R1.multiply(S1);
772                T = new BigRational(T1, IONE);
773                return T;
774            }
775            if (R2.equals(IONE)) {
776                D1 = R1.gcd(S2);
777                RB1 = R1.divide(D1);
778                SB2 = S2.divide(D1);
779                T1 = RB1.multiply(S1);
780                T = new BigRational(T1, SB2);
781                return T;
782            }
783            if (S2.equals(IONE)) {
784                D2 = S1.gcd(R2);
785                SB1 = S1.divide(D2);
786                RB2 = R2.divide(D2);
787                T1 = SB1.multiply(R1);
788                T = new BigRational(T1, RB2);
789                return T;
790            }
791            D1 = R1.gcd(S2);
792            RB1 = R1.divide(D1);
793            SB2 = S2.divide(D1);
794            D2 = S1.gcd(R2);
795            SB1 = S1.divide(D2);
796            RB2 = R2.divide(D2);
797            T1 = RB1.multiply(SB1);
798            T2 = RB2.multiply(SB2);
799            T = new BigRational(T1, T2);
800            return T;
801        }
802    
803    
804        /**
805         * Rational number product.
806         * @param R BigRational.
807         * @param S BigRational.
808         * @return R*S.
809         */
810        public static BigRational RNPROD(BigRational R, BigRational S) {
811            if (R == null) {
812                return R;
813            }
814            return R.multiply(S);
815        }
816    
817    
818        /**
819         * Rational number quotient.
820         * @param S BigRational.
821         * @return this/S.
822         */
823        public BigRational divide(BigRational S) {
824            return multiply(S.inverse());
825        }
826    
827    
828        /**
829         * Rational number quotient.
830         * @param R BigRational.
831         * @param S BigRational.
832         * @return R/S.
833         */
834        public static BigRational RNQ(BigRational R, BigRational S) {
835            if (R == null) {
836                return R;
837            }
838            return R.divide(S);
839        }
840    
841    
842        /**
843         * Rational number remainder.
844         * @param S BigRational.
845         * @return this-(this/S)*S
846         */
847        public BigRational remainder(BigRational S) {
848            if (S.isZERO()) {
849                throw new ArithmeticException("division by zero");
850            }
851            return ZERO;
852        }
853    
854    
855        /**
856         * Rational number, random. Random integers A, B and a random sign s are
857         * generated using BigInteger(n,random) and random.nextBoolen(). Then R =
858         * s*A/(B+1), reduced to lowest terms.
859         * @param n such that 0 &le; A, B &le; (2<sup>n</sup>-1).
860         * @return a random BigRational.
861         */
862        public BigRational random(int n) {
863            return random(n, random);
864        }
865    
866    
867        /**
868         * Rational number, random. Random integers A, B and a random sign s are
869         * generated using BigInteger(n,random) and random.nextBoolen(). Then R =
870         * s*A/(B+1), reduced to lowest terms.
871         * @param n such that 0 &le; A, B &le; (2<sup>n</sup>-1).
872         * @param rnd is a source for random bits.
873         * @return a random BigRational.
874         */
875        public BigRational random(int n, Random rnd) {
876            BigInteger A;
877            BigInteger B;
878            A = new BigInteger(n, rnd); // always positive
879            if (rnd.nextBoolean()) {
880                A = A.negate();
881            }
882            B = new BigInteger(n, rnd); // always positive
883            B = B.add(IONE);
884            return RNRED(A, B);
885        }
886    
887    
888        /**
889         * Rational number, random. Random integers A, B and a random sign s are
890         * generated using BigInteger(n,random) and random.nextBoolen(). Then R =
891         * s*A/(B+1), reduced to lowest terms.
892         * @param NL such that 0 &le; A, B &le; (2<sup>n</sup>-1).
893         * @return a random BigRational.
894         */
895        public static BigRational RNRAND(int NL) {
896            return ONE.random(NL, random);
897        }
898    
899    
900        /**
901         * Rational number sign.
902         * @see edu.jas.structure.RingElem#signum()
903         */
904        public int signum() {
905            return num.signum();
906        }
907    
908    
909        /**
910         * Rational number sign.
911         * @param R BigRational.
912         * @return R.signum().
913         */
914        public static int RNSIGN(BigRational R) {
915            if (R == null) {
916                return 0;
917            }
918            return R.signum();
919        }
920    
921    
922        /**
923         * Rational number sum.
924         * @param S BigRational.
925         * @return this+S.
926         */
927        public BigRational sum(BigRational S) {
928            BigInteger D = null;
929            BigInteger E;
930            BigInteger J1Y;
931            BigInteger J2Y;
932            BigInteger R1 = null;
933            BigInteger R2 = null;
934            BigInteger RB2 = null;
935            BigInteger S1 = null;
936            BigInteger S2 = null;
937            BigInteger SB2 = null;
938            BigRational T;
939            BigInteger T1;
940            BigInteger T2;
941            if (this.equals(ZERO)) {
942                T = S;
943                return T;
944            }
945            if (S.equals(ZERO)) {
946                T = this;
947                return T;
948            }
949            R1 = num; //this.numerator(); 
950            R2 = den; //this.denominator();
951            S1 = S.num;
952            S2 = S.den;
953            if (R2.equals(IONE) && S2.equals(IONE)) {
954                T1 = R1.add(S1);
955                T = new BigRational(T1, IONE);
956                return T;
957            }
958            if (R2.equals(IONE)) {
959                T1 = R1.multiply(S2);
960                T1 = T1.add(S1);
961                T = new BigRational(T1, S2);
962                return T;
963            }
964            if (S2.equals(IONE)) {
965                T1 = R2.multiply(S1);
966                T1 = T1.add(R1);
967                T = new BigRational(T1, R2);
968                return T;
969            }
970            D = R2.gcd(S2);
971            RB2 = R2.divide(D);
972            SB2 = S2.divide(D);
973            J1Y = R1.multiply(SB2);
974            J2Y = RB2.multiply(S1);
975            T1 = J1Y.add(J2Y);
976            if (T1.equals(IZERO)) {
977                T = ZERO;
978                return T;
979            }
980            if (!D.equals(IONE)) {
981                E = T1.gcd(D);
982                if (!E.equals(IONE)) {
983                    T1 = T1.divide(E);
984                    R2 = R2.divide(E);
985                }
986            }
987            T2 = R2.multiply(SB2);
988            T = new BigRational(T1, T2);
989            return T;
990        }
991    
992    
993        /**
994         * Rational number sum.
995         * @param R BigRational.
996         * @param S BigRational.
997         * @return R+S.
998         */
999        public static BigRational RNSUM(BigRational R, BigRational S) {
1000            if (R == null) {
1001                return S;
1002            }
1003            return R.sum(S);
1004        }
1005    
1006    
1007        /**
1008         * Parse rational number from String.
1009         * @param s String.
1010         * @return BigRational from s.
1011         */
1012        public BigRational parse(String s) {
1013            return new BigRational(s);
1014        }
1015    
1016    
1017        /**
1018         * Parse rational number from Reader.
1019         * @param r Reader.
1020         * @return next BigRational from r.
1021         */
1022        public BigRational parse(Reader r) {
1023            return parse(StringUtil.nextString(r));
1024        }
1025    
1026    
1027        /**
1028         * Rational number greatest common divisor.
1029         * @param S BigRational.
1030         * @return gcd(this,S).
1031         */
1032        public BigRational gcd(BigRational S) {
1033            if (S == null || S.isZERO()) {
1034                return this;
1035            }
1036            if (this.isZERO()) {
1037                return S;
1038            }
1039            return ONE;
1040        }
1041    
1042    
1043        /**
1044         * BigRational extended greatest common divisor.
1045         * @param S BigRational.
1046         * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
1047         */
1048        public BigRational[] egcd(BigRational S) {
1049            BigRational[] ret = new BigRational[3];
1050            ret[0] = null;
1051            ret[1] = null;
1052            ret[2] = null;
1053            if (S == null || S.isZERO()) {
1054                ret[0] = this;
1055                return ret;
1056            }
1057            if (this.isZERO()) {
1058                ret[0] = S;
1059                return ret;
1060            }
1061            BigRational half = new BigRational(1, 2);
1062            ret[0] = ONE;
1063            ret[1] = this.inverse().multiply(half);
1064            ret[2] = S.inverse().multiply(half);
1065            return ret;
1066        }
1067    
1068    
1069        private boolean nonNegative = true;
1070    
1071    
1072        private boolean duplicates = true;
1073    
1074    
1075        /**
1076         * Set the iteration algorithm to all elements.
1077         */
1078        public void setAllIterator() {
1079            nonNegative = false;
1080        }
1081    
1082    
1083        /**
1084         * Set the iteration algorithm to non-negative elements.
1085         */
1086        public void setNonNegativeIterator() {
1087            nonNegative = true;
1088        }
1089    
1090    
1091        /**
1092         * Set the iteration algorithm to no duplicate elements.
1093         */
1094        public void setNoDuplicatesIterator() {
1095            duplicates = false;
1096        }
1097    
1098    
1099        /**
1100         * Set the iteration algorithm to allow duplicate elements.
1101         */
1102        public void setDuplicatesIterator() {
1103            duplicates = true;
1104        }
1105    
1106    
1107        /**
1108         * Get a BigInteger iterator.
1109         * @return a iterator over all rationals.
1110         */
1111        public Iterator<BigRational> iterator() {
1112            if (duplicates) {
1113                return new BigRationalIterator(nonNegative);
1114            }
1115            return new BigRationalUniqueIterator(new BigRationalIterator(nonNegative));
1116        }
1117    
1118    
1119        /**
1120         * Get a BigInteger iterator with no duplicates.
1121         * @return a iterator over all rationals without duplicates.
1122         */
1123        public Iterator<BigRational> uniqueIterator() {
1124            return new BigRationalUniqueIterator(new BigRationalIterator(nonNegative));
1125        }
1126    
1127    }
1128    
1129    
1130    /**
1131     * Big rational iterator. Uses Cantors diagonal enumeration.
1132     * @author Heinz Kredel
1133     */
1134    class BigRationalIterator implements Iterator<BigRational> {
1135    
1136    
1137        /**
1138         * data structure.
1139         */
1140        BigRational curr;
1141    
1142    
1143        edu.jas.arith.BigInteger den;
1144    
1145    
1146        edu.jas.arith.BigInteger num;
1147    
1148    
1149        Iterator<edu.jas.arith.BigInteger> denit;
1150    
1151    
1152        Iterator<edu.jas.arith.BigInteger> numit;
1153    
1154    
1155        List<edu.jas.arith.BigInteger> denlist;
1156    
1157    
1158        List<edu.jas.arith.BigInteger> numlist;
1159    
1160    
1161        Iterator<edu.jas.arith.BigInteger> denlistit;
1162    
1163    
1164        Iterator<edu.jas.arith.BigInteger> numlistit;
1165    
1166    
1167        final boolean nonNegative;
1168    
1169    
1170        protected long level;
1171    
1172    
1173        /**
1174         * BigRational iterator constructor.
1175         */
1176        public BigRationalIterator() {
1177            this(false);
1178        }
1179    
1180    
1181        /**
1182         * BigRational iterator constructor.
1183         * @param nn, true for indicator for a non-negative iterator, fall for an
1184         *            all iterator
1185         */
1186        public BigRationalIterator(boolean nn) {
1187            nonNegative = nn;
1188            curr = edu.jas.arith.BigRational.ZERO;
1189            level = 0;
1190            den = new edu.jas.arith.BigInteger(); // ZERO
1191            num = edu.jas.arith.BigInteger.ONE.clone();
1192            if (nn) {
1193                den.setNonNegativeIterator();
1194            } else {
1195                den.setAllIterator();
1196            }
1197            num.setNonNegativeIterator();
1198            denit = den.iterator();
1199            numit = num.iterator();
1200            denlist = new ArrayList<edu.jas.arith.BigInteger>();
1201            numlist = new ArrayList<edu.jas.arith.BigInteger>();
1202            @SuppressWarnings("unused")
1203            edu.jas.arith.BigInteger unused = denit.next(); // skip zero denominator
1204            unused = numit.next();
1205            denlist.add(denit.next());
1206            numlist.add(numit.next());
1207            denlistit = denlist.iterator();
1208            numlistit = numlist.iterator();
1209        }
1210    
1211    
1212        /**
1213         * Test for availability of a next element.
1214         * @return true if the iteration has more elements, else false.
1215         */
1216        public boolean hasNext() {
1217            return true;
1218        }
1219    
1220    
1221        /**
1222         * Get next rational.
1223         * @return next rational.
1224         */
1225        public synchronized BigRational next() {
1226            BigRational r = curr;
1227            if (denlistit.hasNext() && numlistit.hasNext()) {
1228                BigInteger d = denlistit.next().val;
1229                BigInteger n = numlistit.next().val;
1230                //System.out.println(d + "//" + n);
1231                curr = BigRational.reduction(d, n);
1232                return r;
1233            }
1234            level++;
1235            if (level % 2 == 1) {
1236                Collections.reverse(denlist);
1237            } else {
1238                Collections.reverse(numlist);
1239            }
1240            denlist.add(denit.next());
1241            numlist.add(numit.next());
1242            if (level % 2 == 0) {
1243                Collections.reverse(denlist);
1244            } else {
1245                Collections.reverse(numlist);
1246            }
1247            //System.out.println("denlist = " + denlist);
1248            //System.out.println("numlist = " + numlist);
1249            denlistit = denlist.iterator();
1250            numlistit = numlist.iterator();
1251            BigInteger d = denlistit.next().val;
1252            BigInteger n = numlistit.next().val;
1253            //System.out.println(d + "//" + n);
1254            curr = BigRational.reduction(d, n);
1255            return r;
1256        }
1257    
1258    
1259        /**
1260         * Remove an element if allowed.
1261         */
1262        public void remove() {
1263            throw new UnsupportedOperationException("cannnot remove elements");
1264        }
1265    }
1266    
1267    
1268    /**
1269     * Big rational unique iterator. Uses Cantors diagonal enumeration, produces all
1270     * distinct elements.
1271     * @author Heinz Kredel
1272     */
1273    class BigRationalUniqueIterator implements Iterator<BigRational> {
1274    
1275    
1276        /**
1277         * data structure.
1278         */
1279        final Set<BigRational> unique;
1280    
1281    
1282        final Iterator<BigRational> ratit;
1283    
1284    
1285        /**
1286         * BigRational iterator constructor.
1287         */
1288        public BigRationalUniqueIterator() {
1289            this(BigRational.ONE.iterator());
1290        }
1291    
1292    
1293        /**
1294         * BigRational iterator constructor.
1295         * @param nn, true for indicator for a non-negative iterator, fall for an
1296         *            all iterator
1297         */
1298        public BigRationalUniqueIterator(Iterator<BigRational> rit) {
1299            ratit = rit;
1300            unique = new HashSet<BigRational>();
1301        }
1302    
1303    
1304        /**
1305         * Test for availability of a next element.
1306         * @return true if the iteration has more elements, else false.
1307         */
1308        public synchronized boolean hasNext() {
1309            return ratit.hasNext();
1310        }
1311    
1312    
1313        /**
1314         * Get next rational.
1315         * @return next rational.
1316         */
1317        public synchronized BigRational next() {
1318            BigRational r = ratit.next();
1319            while (unique.contains(r)) {
1320                //System.out.println("duplicate " + r);
1321                r = ratit.next();
1322            }
1323            unique.add(r);
1324            return r;
1325        }
1326    
1327    
1328        /**
1329         * Remove an element if allowed.
1330         */
1331        public void remove() {
1332            throw new UnsupportedOperationException("cannnot remove elements");
1333        }
1334    }