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