All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.accelad.math.nilgiri.DoubleDoubleComplex Maven / Gradle / Ivy

The newest version!
package com.accelad.math.nilgiri;

import com.accelad.math.doubledouble.DoubleDouble;

import java.util.Objects;

public class DoubleDoubleComplex implements ComplexNumber {

    public static final DoubleDoubleComplex I = new DoubleDoubleComplex(0.0, 1.0);
    public static final DoubleDoubleComplex ONE = new DoubleDoubleComplex(1.0, 0.0);
    public static final DoubleDoubleComplex ZERO = new DoubleDoubleComplex(0.0, 0.0);

    private static final DoubleDoubleComplex TEN = new DoubleDoubleComplex(10.0, 0.0);
    private static final DoubleDoubleComplex LOG_TEN = TEN.log();
    private static final DoubleDoubleComplex NAN = new DoubleDoubleComplex(
            new DoubleDoubleReal(DoubleDouble.NaN), new DoubleDoubleReal(DoubleDouble.NaN));

    private final DoubleDoubleReal imaginary;
    private final DoubleDoubleReal real;

    public DoubleDoubleComplex() {
        this(0, 0);
    }

    public DoubleDoubleComplex(double real) {
        this(real, 0.0);
    }

    public DoubleDoubleComplex(double real, double imaginary) {
        this(new DoubleDoubleReal(real), new DoubleDoubleReal(imaginary));
    }

    public DoubleDoubleComplex(DoubleDoubleReal real) {
        this(real, new DoubleDoubleReal());
    }

    public DoubleDoubleComplex(DoubleDouble real, DoubleDouble imaginary) {
        this(new DoubleDoubleReal(real), new DoubleDoubleReal(imaginary));
    }

    public DoubleDoubleComplex(DoubleDoubleReal real, DoubleDoubleReal imaginary) {
        this.real = real;
        this.imaginary = imaginary;
    }

    @Override
    public double getImaginary() {
        return imaginary.doubleValue();
    }

    @Override
    public double getReal() {
        return real.doubleValue();
    }

    @Override
    public DoubleDoubleComplex inverse() {
        return ONE.div(this);
    }

    @Override
    public DoubleDoubleComplex div(DoubleDoubleComplex divisor) {
        DoubleDoubleReal denominator = divisor.real.pow(2).plus(divisor.imaginary.pow(2));
        DoubleDoubleReal realPart = real.mul(divisor.real)
                                        .plus(imaginary.mul(divisor.imaginary))
                                        .div(denominator);
        DoubleDoubleReal imaginaryPart = imaginary.mul(divisor.real)
                                                  .minus(real.mul(divisor.imaginary))
                                                  .div(denominator);
        return new DoubleDoubleComplex(realPart, imaginaryPart);
    }

    @Override
    public DoubleDoubleComplex plus(DoubleDoubleComplex plusend) {
        return new DoubleDoubleComplex(real.plus(plusend.real), imaginary.plus(plusend.imaginary));
    }

    @Override
    public DoubleDoubleComplex minus(DoubleDoubleComplex subtrahend) {
        return new DoubleDoubleComplex(real.minus(subtrahend.real),
                imaginary.minus(subtrahend.imaginary));
    }

    @Override
    public DoubleDoubleComplex mul(long factor) {
        return mul(new DoubleDoubleComplex(factor));
    }

    @Override
    public DoubleDoubleComplex negate() {
        return new DoubleDoubleComplex(real.negate(), imaginary.negate());
    }

    @Override
    public DoubleDoubleComplex mul(DoubleDoubleComplex factor) {
        return new DoubleDoubleComplex(real.mul(factor.real).minus(imaginary.mul(factor.imaginary)),
                real.mul(factor.imaginary).plus(imaginary.mul(factor.real)));
    }

    public DoubleDoubleComplex abs() {
        return new DoubleDoubleComplex(real.pow(2).plus(imaginary.pow(2)).sqrt(),
                DoubleDoubleReal.ZERO);
    }

    @Override
    public DoubleDoubleComplex pow(int n) {
        if (this.equals(ZERO)) {
            if (n == 0) {
                return NAN;
            } else {
                return ZERO;
            }
        } else if (n == 0) {
            return ONE;
        } else {
            DoubleDoubleComplex result = ZERO;
            for (int k = 0; k <= n; k++) {
                result = result.plus(powI(k).mul(binomialCoeff(n, k))
                                            .mul(new DoubleDoubleComplex(real.pow(n - k),
                                                    DoubleDoubleReal.ZERO))
                                            .mul(new DoubleDoubleComplex(imaginary.pow(k),
                                                    DoubleDoubleReal.ZERO)));
            }
            return result;
        }
    }

    public DoubleDoubleComplex exp() {
        DoubleDoubleReal expReal = real.exp();
        return new DoubleDoubleComplex(expReal.mul(imaginary.cos()), expReal.mul(imaginary.sin()));
    }

    public DoubleDoubleComplex log() {
        DoubleDoubleReal real = this.abs().re().log();
        DoubleDouble imaginaryPart = DoubleDouble.atan2(this.imaginary.getDoubleDouble(), this.real.getDoubleDouble());
        return new DoubleDoubleComplex(real, new DoubleDoubleReal(imaginaryPart));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DoubleDoubleComplex that = (DoubleDoubleComplex) o;
        return Objects.equals(imaginary, that.imaginary) &&
                Objects.equals(real, that.real);
    }

    @Override
    public int hashCode() {
        return Objects.hash(imaginary, real);
    }

    @Override
    public String toString() {
        return "DoubleDoubleComplex{" +
                "imaginary=" + imaginary +
                ", real=" + real +
                '}';
    }

    @Override
    public DoubleDoubleComplex conjugate() {
        return new DoubleDoubleComplex(real, imaginary.negate());
    }

    @Override
    public DoubleDoubleReal re() {
        return real;
    }

    @Override
    public DoubleDoubleReal im() {
        return imaginary;
    }

    public DoubleDoubleComplex cos() {
        DoubleDoubleComplex d1 = new DoubleDoubleComplex(imaginary.negate(), real).exp();
        DoubleDoubleComplex d2 = new DoubleDoubleComplex(imaginary, real.negate()).exp();
        return d1.plus(d2).mul(new DoubleDoubleComplex(.5));
    }

    public DoubleDoubleComplex sin() {
        DoubleDoubleComplex d1 = new DoubleDoubleComplex(imaginary, real.negate()).exp();
        DoubleDoubleComplex d2 = new DoubleDoubleComplex(imaginary.negate(), real).exp();
        return d1.minus(d2).mul(new DoubleDoubleComplex(0, .5));
    }

    public DoubleDoubleComplex tan() {
        return sin().div(cos());
    }

    public DoubleDoubleComplex pow(DoubleDoubleComplex pow) {
        return log().mul(pow).exp();
    }

    public DoubleDoubleComplex sqrt() {
        DoubleDoubleReal realPart = real.plus(abs().re()).div(DoubleDoubleReal.TWO).sqrt();
        DoubleDoubleReal imaginaryPart = abs().re().minus(real).div(DoubleDoubleReal.TWO).sqrt();
        return new DoubleDoubleComplex(realPart, imaginaryPart);
    }

    public DoubleDoubleComplex acos() {
        return this.plus(ONE.minus(this.pow(2)).sqrt().mul(I)).log().mul(I.negate());
    }

    public DoubleDoubleComplex asin() {
        return ONE.minus(this.pow(2)).sqrt().plus(this.mul(I)).log().mul(I.negate());
    }

    public DoubleDoubleComplex atan() {
        return this.plus(I).div(I.minus(this)).log().mul(I.div(new DoubleDoubleComplex(2.0, 0.0)));
    }

    public DoubleDoubleComplex acosh() {
        return this.plus(this.plus(ONE).sqrt().mul(this.minus(ONE).sqrt())).log();
    }

    public DoubleDoubleComplex asinh() {
        return this.plus(ONE.plus(this.pow(2)).sqrt()).log();
    }

    public DoubleDoubleComplex cosh() {
        return new DoubleDoubleComplex(real.cosh().mul(imaginary.cos()),
                real.sinh().mul(imaginary.sin()));
    }

    public DoubleDoubleComplex sinh() {
        return new DoubleDoubleComplex(real.sinh().mul(imaginary.cos()),
                real.cosh().mul(imaginary.sin()));
    }

    public DoubleDoubleComplex tanh() {
        DoubleDoubleReal real2 = real.mul(2);
        DoubleDoubleReal imaginary2 = imaginary.mul(2);
        DoubleDoubleReal d = real2.cosh().plus(imaginary2.cos());
        return new DoubleDoubleComplex(real2.sinh().div(d), imaginary2.sin().div(d));
    }

    public DoubleDoubleComplex atanh() {
        return ONE.plus(this).log().minus(ONE.minus(this).log()).div(new DoubleDoubleComplex(2));
    }

    public DoubleDoubleComplex log10() {
        return this.log().div(LOG_TEN);
    }

    public DoubleDoubleComplex pwr(DoubleDoubleComplex i_y) {
        return this.abs().pow(i_y);
    }

    private DoubleDoubleComplex binomialCoeff(int n, int k) {
        int res = 1;
        if (k > n - k)
            k = n - k;
        for (int i = 0; i < k; ++i) {
            res *= (n - i);
            res /= (i + 1);
        }
        return new DoubleDoubleComplex(res);
    }

    private DoubleDoubleComplex powI(int n) {
        switch (n % 4) {
        case 0:
            return ONE;
        case 1:
            return I;
        case 2:
            return ONE.negate();
        case 3:
            return I.negate();
        }
        throw null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy