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 ≤ A, B ≤ (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 ≤ A, B ≤ (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 ≤ A, B ≤ (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}