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