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