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