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 }