001/* 002 * $Id: BigQuaternion.java 4640 2013-09-14 11:32:01Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008import java.io.Reader; 009import java.math.BigInteger; 010import java.util.ArrayList; 011import java.util.List; 012import java.util.Random; 013 014import org.apache.log4j.Logger; 015 016import edu.jas.kern.StringUtil; 017import edu.jas.structure.GcdRingElem; 018import edu.jas.structure.RingFactory; 019import edu.jas.structure.StarRingElem; 020 021 022/** 023 * BigQuaternion class based on BigRational implementing the RingElem interface 024 * and with the familiar MAS static method names. Objects of this class are 025 * immutable. 026 * @author Heinz Kredel 027 */ 028 029public final class BigQuaternion implements StarRingElem<BigQuaternion>, GcdRingElem<BigQuaternion>, 030 RingFactory<BigQuaternion> { 031 032 033 /** 034 * Real part of the data structure. 035 */ 036 public final BigRational re; // real part 037 038 039 /** 040 * Imaginary part i of the data structure. 041 */ 042 public final BigRational im; // i imaginary part 043 044 045 /** 046 * Imaginary part j of the data structure. 047 */ 048 public final BigRational jm; // j imaginary part 049 050 051 /** 052 * Imaginary part k of the data structure. 053 */ 054 public final BigRational km; // k imaginary part 055 056 057 private final static Random random = new Random(); 058 059 060 private static final Logger logger = Logger.getLogger(BigQuaternion.class); 061 062 063 private final boolean debug = logger.isDebugEnabled(); 064 065 066 /** 067 * Constructor for a BigQuaternion from BigRationals. 068 * @param r BigRational. 069 * @param i BigRational. 070 * @param j BigRational. 071 * @param k BigRational. 072 */ 073 public BigQuaternion(BigRational r, BigRational i, BigRational j, BigRational k) { 074 re = r; 075 im = i; 076 jm = j; 077 km = k; 078 } 079 080 081 /** 082 * Constructor for a BigQuaternion from BigRationals. 083 * @param r BigRational. 084 * @param i BigRational. 085 * @param j BigRational. 086 */ 087 public BigQuaternion(BigRational r, BigRational i, BigRational j) { 088 this(r, i, j, BigRational.ZERO); 089 } 090 091 092 /** 093 * Constructor for a BigQuaternion from BigRationals. 094 * @param r BigRational. 095 * @param i BigRational. 096 */ 097 public BigQuaternion(BigRational r, BigRational i) { 098 this(r, i, BigRational.ZERO); 099 } 100 101 102 /** 103 * Constructor for a BigQuaternion from BigRationals. 104 * @param r BigRational. 105 */ 106 public BigQuaternion(BigRational r) { 107 this(r, BigRational.ZERO); 108 } 109 110 111 /** 112 * Constructor for a BigQuaternion from BigComplex. 113 * @param r BigComplex. 114 */ 115 public BigQuaternion(BigComplex r) { 116 this(r.re, r.im); 117 } 118 119 120 /** 121 * Constructor for a BigQuaternion from long. 122 * @param r long. 123 */ 124 public BigQuaternion(long r) { 125 this(new BigRational(r), BigRational.ZERO); 126 } 127 128 129 /** 130 * Constructor for a BigQuaternion with no arguments. 131 */ 132 public BigQuaternion() { 133 this(BigRational.ZERO); 134 } 135 136 137 /** 138 * The BigQuaternion string constructor accepts the following formats: empty 139 * string, "rational", or "rat i rat j rat k rat" with no blanks around i, j 140 * or k if used as polynoial coefficient. 141 * @param s String. 142 * @throws NumberFormatException 143 */ 144 public BigQuaternion(String s) throws NumberFormatException { 145 if (s == null || s.length() == 0) { 146 re = BigRational.ZERO; 147 im = BigRational.ZERO; 148 jm = BigRational.ZERO; 149 km = BigRational.ZERO; 150 return; 151 } 152 s = s.trim(); 153 int r = s.indexOf("i") + s.indexOf("j") + s.indexOf("k"); 154 if (r == -3) { 155 re = new BigRational(s); 156 im = BigRational.ZERO; 157 jm = BigRational.ZERO; 158 km = BigRational.ZERO; 159 return; 160 } 161 162 int i = s.indexOf("i"); 163 String sr = ""; 164 if (i > 0) { 165 sr = s.substring(0, i); 166 } else if (i < 0) { 167 throw new NumberFormatException("BigQuaternion missing i"); 168 } 169 String si = ""; 170 if (i < s.length()) { 171 s = s.substring(i + 1, s.length()); 172 } 173 int j = s.indexOf("j"); 174 if (j > 0) { 175 si = s.substring(0, j); 176 } else if (j < 0) { 177 throw new NumberFormatException("BigQuaternion missing j"); 178 } 179 String sj = ""; 180 if (j < s.length()) { 181 s = s.substring(j + 1, s.length()); 182 } 183 int k = s.indexOf("k"); 184 if (k > 0) { 185 sj = s.substring(0, k); 186 } else if (k < 0) { 187 throw new NumberFormatException("BigQuaternion missing k"); 188 } 189 String sk = ""; 190 if (k < s.length()) { 191 s = s.substring(k + 1, s.length()); 192 } 193 sk = s; 194 195 re = new BigRational(sr.trim()); 196 im = new BigRational(si.trim()); 197 jm = new BigRational(sj.trim()); 198 km = new BigRational(sk.trim()); 199 } 200 201 202 /** 203 * Get the corresponding element factory. 204 * @return factory for this Element. 205 * @see edu.jas.structure.Element#factory() 206 */ 207 public BigQuaternion factory() { 208 return this; 209 } 210 211 212 /** 213 * Get a list of the generating elements. 214 * @return list of generators for the algebraic structure. 215 * @see edu.jas.structure.ElemFactory#generators() 216 */ 217 public List<BigQuaternion> generators() { 218 List<BigQuaternion> g = new ArrayList<BigQuaternion>(4); 219 g.add(getONE()); 220 g.add(I); 221 g.add(J); 222 g.add(K); 223 return g; 224 } 225 226 227 /** 228 * Is this structure finite or infinite. 229 * @return true if this structure is finite, else false. 230 * @see edu.jas.structure.ElemFactory#isFinite() 231 */ 232 public boolean isFinite() { 233 return false; 234 } 235 236 237 /** 238 * Clone this. 239 * @see java.lang.Object#clone() 240 */ 241 @Override 242 public BigQuaternion copy() { 243 return new BigQuaternion(re, im, jm, km); 244 } 245 246 247 /** 248 * Copy BigQuaternion element c. 249 * @param c BigQuaternion. 250 * @return a copy of c. 251 */ 252 public BigQuaternion copy(BigQuaternion c) { 253 return new BigQuaternion(c.re, c.im, c.jm, c.km); 254 } 255 256 257 /** 258 * Get the zero element. 259 * @return 0 as BigQuaternion. 260 */ 261 public BigQuaternion getZERO() { 262 return ZERO; 263 } 264 265 266 /** 267 * Get the one element. 268 * @return q as BigQuaternion. 269 */ 270 public BigQuaternion getONE() { 271 return ONE; 272 } 273 274 275 /** 276 * Query if this ring is commutative. 277 * @return false. 278 */ 279 public boolean isCommutative() { 280 return false; 281 } 282 283 284 /** 285 * Query if this ring is associative. 286 * @return true. 287 */ 288 public boolean isAssociative() { 289 return true; 290 } 291 292 293 /** 294 * Query if this ring is a field. 295 * @return true. 296 */ 297 public boolean isField() { 298 return true; 299 } 300 301 302 /** 303 * Characteristic of this ring. 304 * @return characteristic of this ring. 305 */ 306 public java.math.BigInteger characteristic() { 307 return java.math.BigInteger.ZERO; 308 } 309 310 311 /** 312 * Get a BigQuaternion element from a BigInteger. 313 * @param a BigInteger. 314 * @return a BigQuaternion. 315 */ 316 public BigQuaternion fromInteger(BigInteger a) { 317 return new BigQuaternion(new BigRational(a)); 318 } 319 320 321 /** 322 * Get a BigQuaternion element from a long. 323 * @param a long. 324 * @return a BigQuaternion. 325 */ 326 public BigQuaternion fromInteger(long a) { 327 return new BigQuaternion(new BigRational(a)); 328 } 329 330 331 /** 332 * The constant 0. 333 */ 334 public static final BigQuaternion ZERO = new BigQuaternion(); 335 336 337 /** 338 * The constant 1. 339 */ 340 public static final BigQuaternion ONE = new BigQuaternion(BigRational.ONE); 341 342 343 /** 344 * The constant i. 345 */ 346 public static final BigQuaternion I = new BigQuaternion(BigRational.ZERO, BigRational.ONE); 347 348 349 /** 350 * The constant j. 351 */ 352 public static final BigQuaternion J = new BigQuaternion(BigRational.ZERO, BigRational.ZERO, 353 BigRational.ONE); 354 355 356 /** 357 * The constant k. 358 */ 359 public static final BigQuaternion K = new BigQuaternion(BigRational.ZERO, BigRational.ZERO, 360 BigRational.ZERO, BigRational.ONE); 361 362 363 /** 364 * Get the real part. 365 * @return re. 366 */ 367 public BigRational getRe() { 368 return re; 369 } 370 371 372 /** 373 * Get the imaginary part im. 374 * @return im. 375 */ 376 public BigRational getIm() { 377 return im; 378 } 379 380 381 /** 382 * Get the imaginary part jm. 383 * @return jm. 384 */ 385 public BigRational getJm() { 386 return jm; 387 } 388 389 390 /** 391 * Get the imaginary part km. 392 * @return km. 393 */ 394 public BigRational getKm() { 395 return km; 396 } 397 398 399 /** 400 * Get the string representation. Is compatible with the string constructor. 401 * @see java.lang.Object#toString() 402 */ 403 @Override 404 public String toString() { 405 String s = "" + re; 406 int i = im.compareTo(BigRational.ZERO); 407 int j = jm.compareTo(BigRational.ZERO); 408 int k = km.compareTo(BigRational.ZERO); 409 if (debug) { 410 logger.debug("compareTo " + im + " ? 0 = " + i); 411 logger.debug("compareTo " + jm + " ? 0 = " + j); 412 logger.debug("compareTo " + km + " ? 0 = " + k); 413 } 414 if (i == 0 && j == 0 && k == 0) 415 return s; 416 s += "i" + im; 417 s += "j" + jm; 418 s += "k" + km; 419 return s; 420 } 421 422 423 /** 424 * Get a scripting compatible string representation. 425 * @return script compatible representation for this Element. 426 * @see edu.jas.structure.Element#toScript() 427 */ 428 @Override 429 public String toScript() { 430 // Python case 431 StringBuffer s = new StringBuffer(); 432 boolean i = im.isZERO(); 433 boolean j = jm.isZERO(); 434 boolean k = km.isZERO(); 435 if (i && j && k) { 436 if (re.isZERO()) { 437 return "0 "; 438 } 439 if (!re.isONE()) { 440 s.append(re.toScript() + "*"); 441 } 442 s.append("oneQ "); 443 return s.toString(); 444 } 445 if (!re.isZERO()) { 446 if (!re.isONE()) { 447 s.append(re.toScript() + "*"); 448 } 449 s.append("oneQ "); 450 } 451 if (!i) { 452 if (s.length() > 0) { 453 s.append("+ "); 454 } 455 if (!im.isONE()) { 456 s.append(im.toScript() + "*"); 457 } 458 s.append("IQ "); 459 } 460 if (!j) { 461 if (s.length() > 0) { 462 s.append("+ "); 463 } 464 if (!jm.isONE()) { 465 s.append(jm.toScript() + "*"); 466 } 467 s.append("JQ "); 468 } 469 if (!k) { 470 if (s.length() > 0) { 471 s.append("+ "); 472 } 473 if (!km.isONE()) { 474 s.append(km.toScript() + "*"); 475 } 476 s.append("KQ "); 477 } 478 return s.toString(); 479 } 480 481 482 /** 483 * Get a scripting compatible string representation of the factory. 484 * @return script compatible representation for this ElemFactory. 485 * @see edu.jas.structure.Element#toScriptFactory() 486 */ 487 @Override 488 public String toScriptFactory() { 489 // Python case 490 return "Quat()"; 491 } 492 493 494 /** 495 * Is Quaternion number zero. 496 * @param A BigQuaternion. 497 * @return true if A is 0, else false. 498 */ 499 public static boolean isQZERO(BigQuaternion A) { 500 if (A == null) 501 return false; 502 return A.isZERO(); 503 } 504 505 506 /** 507 * Is BigQuaternion number zero. 508 * @return true if this is 0, else false. 509 * @see edu.jas.structure.RingElem#isZERO() 510 */ 511 public boolean isZERO() { 512 return re.equals(BigRational.ZERO) && im.equals(BigRational.ZERO) && jm.equals(BigRational.ZERO) 513 && km.equals(BigRational.ZERO); 514 } 515 516 517 /** 518 * Is BigQuaternion number one. 519 * @param A is a quaternion number. 520 * @return true if A is 1, else false. 521 */ 522 public static boolean isQONE(BigQuaternion A) { 523 if (A == null) 524 return false; 525 return A.isONE(); 526 } 527 528 529 /** 530 * Is BigQuaternion number one. 531 * @see edu.jas.structure.RingElem#isONE() 532 * @return true if this is 1, else false. 533 */ 534 public boolean isONE() { 535 return re.equals(BigRational.ONE) && im.equals(BigRational.ZERO) && jm.equals(BigRational.ZERO) 536 && km.equals(BigRational.ZERO); 537 } 538 539 540 /** 541 * Is BigQuaternion imaginary one. 542 * @return true if this is i, else false. 543 */ 544 public boolean isIMAG() { 545 return re.equals(BigRational.ZERO) && im.equals(BigRational.ONE) && jm.equals(BigRational.ZERO) 546 && km.equals(BigRational.ZERO); 547 } 548 549 550 /** 551 * Is BigQuaternion unit element. 552 * @return If this is a unit then true is returned, else false. 553 * @see edu.jas.structure.RingElem#isUnit() 554 */ 555 public boolean isUnit() { 556 return (!isZERO()); 557 } 558 559 560 /** 561 * Comparison with any other object. 562 * @see java.lang.Object#equals(java.lang.Object) 563 */ 564 @Override 565 public boolean equals(Object b) { 566 if (!(b instanceof BigQuaternion)) 567 return false; 568 BigQuaternion B = (BigQuaternion) b; 569 return re.equals(B.re) && im.equals(B.im) && jm.equals(B.jm) && km.equals(B.km); 570 } 571 572 573 /** 574 * Hash code for this BigQuaternion. 575 * @see java.lang.Object#hashCode() 576 */ 577 @Override 578 public int hashCode() { 579 int h; 580 h = 37 * re.hashCode(); 581 h += 37 * im.hashCode(); 582 h += 37 * jm.hashCode(); 583 h += 37 * km.hashCode(); 584 return h; 585 } 586 587 588 /** 589 * Since quaternion numbers are unordered, we use lexicographical order of 590 * re, im, jm and km. 591 * @param b BigQuaternion. 592 * @return 0 if b is equal to this, 1 if this is greater b and -1 else. 593 */ 594 @Override 595 public int compareTo(BigQuaternion b) { 596 int s = re.compareTo(b.re); 597 if (s != 0) { 598 return s; 599 } 600 s = im.compareTo(b.im); 601 if (s != 0) { 602 return s; 603 } 604 s = jm.compareTo(b.jm); 605 if (s != 0) { 606 return s; 607 } 608 return km.compareTo(b.km); 609 } 610 611 612 /** 613 * Since quaternion numbers are unordered, we use lexicographical order of 614 * re, im, jm and km. 615 * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0, or 616 * ...; -1 if re < 0, or re == 0 and im < 0, or ... 617 * @see edu.jas.structure.RingElem#signum() 618 */ 619 public int signum() { 620 int s = re.signum(); 621 if (s != 0) { 622 return s; 623 } 624 s = im.signum(); 625 if (s != 0) { 626 return s; 627 } 628 s = jm.signum(); 629 if (s != 0) { 630 return s; 631 } 632 return km.signum(); 633 } 634 635 636 /* arithmetic operations: +, -, - 637 */ 638 639 /** 640 * BigQuaternion summation. 641 * @param B BigQuaternion. 642 * @return this+B. 643 */ 644 public BigQuaternion sum(BigQuaternion B) { 645 return new BigQuaternion(re.sum(B.re), im.sum(B.im), jm.sum(B.jm), km.sum(B.km)); 646 } 647 648 649 /** 650 * Quaternion number sum. 651 * @param A BigQuaternion. 652 * @param B BigQuaternion. 653 * @return A+B. 654 */ 655 public static BigQuaternion QSUM(BigQuaternion A, BigQuaternion B) { 656 if (A == null) 657 return null; 658 return A.sum(B); 659 } 660 661 662 /** 663 * Quaternion number difference. 664 * @param A BigQuaternion. 665 * @param B BigQuaternion. 666 * @return A-B. 667 */ 668 public static BigQuaternion QDIF(BigQuaternion A, BigQuaternion B) { 669 if (A == null) 670 return null; 671 return A.subtract(B); 672 } 673 674 675 /** 676 * BigQuaternion subtraction. 677 * @param B BigQuaternion. 678 * @return this-B. 679 */ 680 public BigQuaternion subtract(BigQuaternion B) { 681 return new BigQuaternion(re.subtract(B.re), im.subtract(B.im), jm.subtract(B.jm), km.subtract(B.km)); 682 } 683 684 685 /** 686 * Quaternion number negative. 687 * @param A is a quaternion number 688 * @return -A. 689 */ 690 public static BigQuaternion QNEG(BigQuaternion A) { 691 if (A == null) 692 return null; 693 return A.negate(); 694 } 695 696 697 /** 698 * BigQuaternion number negative. 699 * @return -this. 700 * @see edu.jas.structure.RingElem#negate() 701 */ 702 public BigQuaternion negate() { 703 return new BigQuaternion(re.negate(), im.negate(), jm.negate(), km.negate()); 704 } 705 706 707 /** 708 * Quaternion number conjugate. 709 * @param A is a quaternion number. 710 * @return the quaternion conjugate of A. 711 */ 712 public static BigQuaternion QCON(BigQuaternion A) { 713 if (A == null) 714 return null; 715 return A.conjugate(); 716 } 717 718 719 /* arithmetic operations: conjugate, absolute value 720 */ 721 722 /** 723 * BigQuaternion conjugate. 724 * @return conjugate(this). 725 */ 726 public BigQuaternion conjugate() { 727 return new BigQuaternion(re, im.negate(), jm.negate(), km.negate()); 728 } 729 730 731 /** 732 * Quaternion number norm. 733 * @see edu.jas.structure.StarRingElem#norm() 734 * @return ||this||. 735 */ 736 public BigQuaternion norm() { 737 // this.conjugate().multiply(this); 738 BigRational v = re.multiply(re); 739 v = v.sum(im.multiply(im)); 740 v = v.sum(jm.multiply(jm)); 741 v = v.sum(km.multiply(km)); 742 return new BigQuaternion(v); 743 } 744 745 746 /** 747 * Quaternion number absolute value. 748 * @see edu.jas.structure.RingElem#abs() 749 * @return |this|^2. Note: The square root is not jet implemented. 750 */ 751 public BigQuaternion abs() { 752 BigQuaternion n = norm(); 753 logger.error("abs() square root missing"); 754 // n = n.sqrt(); 755 return n; 756 } 757 758 759 /** 760 * Quaternion number absolute value. 761 * @param A is a quaternion number. 762 * @return the absolute value of A, a rational number. Note: The square root 763 * is not jet implemented. 764 */ 765 public static BigRational QABS(BigQuaternion A) { 766 if (A == null) 767 return null; 768 return A.abs().re; 769 } 770 771 772 /** 773 * Quaternion number product. 774 * @param A BigQuaternion. 775 * @param B BigQuaternion. 776 * @return A*B. 777 */ 778 public static BigQuaternion QPROD(BigQuaternion A, BigQuaternion B) { 779 if (A == null) 780 return null; 781 return A.multiply(B); 782 } 783 784 785 /* arithmetic operations: *, inverse, / 786 */ 787 788 /** 789 * BigQuaternion multiply. 790 * @param B BigQuaternion. 791 * @return this*B. 792 */ 793 public BigQuaternion multiply(BigQuaternion B) { 794 BigRational r = re.multiply(B.re); 795 r = r.subtract(im.multiply(B.im)); 796 r = r.subtract(jm.multiply(B.jm)); 797 r = r.subtract(km.multiply(B.km)); 798 BigRational i = re.multiply(B.im); 799 i = i.sum(im.multiply(B.re)); 800 i = i.sum(jm.multiply(B.km)); 801 i = i.subtract(km.multiply(B.jm)); 802 803 BigRational j = re.multiply(B.jm); 804 j = j.subtract(im.multiply(B.km)); 805 j = j.sum(jm.multiply(B.re)); 806 j = j.sum(km.multiply(B.im)); 807 808 BigRational k = re.multiply(B.km); 809 k = k.sum(im.multiply(B.jm)); 810 k = k.subtract(jm.multiply(B.im)); 811 k = k.sum(km.multiply(B.re)); 812 813 return new BigQuaternion(r, i, j, k); 814 } 815 816 817 /** 818 * Quaternion number inverse. 819 * @param A is a non-zero quaternion number. 820 * @return S with S * A = 1. 821 */ 822 public static BigQuaternion QINV(BigQuaternion A) { 823 if (A == null) 824 return null; 825 return A.inverse(); 826 } 827 828 829 /** 830 * BigQuaternion inverse. 831 * @return S with S * this = 1. 832 * @see edu.jas.structure.RingElem#inverse() 833 */ 834 public BigQuaternion inverse() { 835 BigRational a = norm().re.inverse(); 836 return new BigQuaternion(re.multiply(a), im.multiply(a.negate()), jm.multiply(a.negate()), 837 km.multiply(a.negate())); 838 } 839 840 841 /** 842 * BigQuaternion remainder. 843 * @param S BigQuaternion. 844 * @return 0. 845 */ 846 public BigQuaternion remainder(BigQuaternion S) { 847 if (S.isZERO()) { 848 throw new ArithmeticException("division by zero"); 849 } 850 return ZERO; 851 } 852 853 854 /** 855 * Quaternion number quotient. 856 * @param A BigQuaternion. 857 * @param B BigQuaternion. 858 * @return R/S. 859 */ 860 public static BigQuaternion QQ(BigQuaternion A, BigQuaternion B) { 861 if (A == null) 862 return null; 863 return A.divide(B); 864 } 865 866 867 /** 868 * BigQuaternion divide. 869 * @param b BigQuaternion. 870 * @return this/b. 871 */ 872 public BigQuaternion divide(BigQuaternion b) { 873 return this.multiply(b.inverse()); 874 } 875 876 877 /** 878 * BigQuaternion divide. 879 * @param b BigRational. 880 * @return this/b. 881 */ 882 public BigQuaternion divide(BigRational b) { 883 BigRational bi = b.inverse(); 884 return new BigQuaternion(re.multiply(bi), im.multiply(bi), jm.multiply(bi), km.multiply(bi)); 885 } 886 887 888 /** 889 * Quotient and remainder by division of this by S. 890 * @param S a quaternion number 891 * @return [this/S, this - (this/S)*S]. 892 */ 893 public BigQuaternion[] quotientRemainder(BigQuaternion S) { 894 return new BigQuaternion[] { divide(S), ZERO }; 895 } 896 897 898 /** 899 * BigQuaternion random. Random rational numbers A, B, C and D are generated 900 * using random(n). Then R is the quaternion number with real part A and 901 * imaginary parts B, C and D. 902 * @param n such that 0 ≤ A, B, C, D ≤ (2<sup>n</sup>-1). 903 * @return R, a random BigQuaternion. 904 */ 905 public BigQuaternion random(int n) { 906 return random(n, random); 907 } 908 909 910 /** 911 * BigQuaternion random. Random rational numbers A, B, C and D are generated 912 * using RNRAND(n). Then R is the quaternion number with real part A and 913 * imaginary parts B, C and D. 914 * @param n such that 0 ≤ A, B, C, D ≤ (2<sup>n</sup>-1). 915 * @param rnd is a source for random bits. 916 * @return R, a random BigQuaternion. 917 */ 918 public BigQuaternion random(int n, Random rnd) { 919 BigRational r = BigRational.ONE.random(n, rnd); 920 BigRational i = BigRational.ONE.random(n, rnd); 921 BigRational j = BigRational.ONE.random(n, rnd); 922 BigRational k = BigRational.ONE.random(n, rnd); 923 return new BigQuaternion(r, i, j, k); 924 } 925 926 927 /** 928 * Quaternion number, random. Random rational numbers A, B, C and D are 929 * generated using RNRAND(n). Then R is the quaternion number with real part 930 * A and imaginary parts B, C and D. 931 * @param n such that 0 ≤ A, B, C, D ≤ (2<sup>n</sup>-1). 932 * @return R, a random BigQuaternion. 933 */ 934 public static BigQuaternion QRAND(int n) { 935 return ONE.random(n, random); 936 } 937 938 939 /** 940 * Parse quaternion number from String. 941 * @param s String. 942 * @return BigQuaternion from s. 943 */ 944 public BigQuaternion parse(String s) { 945 return new BigQuaternion(s); 946 } 947 948 949 /** 950 * Parse quaternion number from Reader. 951 * @param r Reader. 952 * @return next BigQuaternion from r. 953 */ 954 public BigQuaternion parse(Reader r) { 955 return parse(StringUtil.nextString(r)); 956 } 957 958 959 /** 960 * Quaternion number greatest common divisor. 961 * @param S BigQuaternion. 962 * @return gcd(this,S). 963 */ 964 public BigQuaternion gcd(BigQuaternion S) { 965 if (S == null || S.isZERO()) { 966 return this; 967 } 968 if (this.isZERO()) { 969 return S; 970 } 971 return ONE; 972 } 973 974 975 /** 976 * BigQuaternion extended greatest common divisor. 977 * @param S BigQuaternion. 978 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 979 */ 980 public BigQuaternion[] egcd(BigQuaternion S) { 981 BigQuaternion[] ret = new BigQuaternion[3]; 982 ret[0] = null; 983 ret[1] = null; 984 ret[2] = null; 985 if (S == null || S.isZERO()) { 986 ret[0] = this; 987 return ret; 988 } 989 if (this.isZERO()) { 990 ret[0] = S; 991 return ret; 992 } 993 BigQuaternion half = new BigQuaternion(new BigRational(1, 2)); 994 ret[0] = ONE; 995 ret[1] = this.inverse().multiply(half); 996 ret[2] = S.inverse().multiply(half); 997 return ret; 998 } 999 1000}