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