/*
* Class Complex
*
* Defines a complex number as an object and includes
* the methods needed for standard complex arithmetic
*
* See class ComplexMatrix for complex matrix manipulations
* See class ComplexPoly for complex polynomial manipulations
* See class ComplexErrorProp for the error propogation in complex arithmetic
*
* WRITTEN BY: Dr Michael Thomas Flanagan
*
* DATE: February 2002
* UPDATED: 13 April 2004, 18 January 2005
*
* DOCUMENTATION:
* See Michael T Flanagan's Java library on-line web page:
* Complex.html
*
* Copyright (c) April 2004 Michael Thomas Flanagan
*
* PERMISSION TO COPY:
* Permission to use, copy and modify this software and its documentation for
* NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement
* to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies.
*
* Dr Michael Thomas Flanagan makes no representations about the suitability
* or fitness of the software for any or for a particular purpose.
* Michael Thomas Flanagan shall not be liable for any damages suffered
* as a result of using, modifying or distributing this software or its derivatives.
*
***************************************************************************************/
package jass.utils;
public class Complex{
// DATA VARIABLES
private double real = 0.0D; // Real part of a complex number
private double imag = 0.0D; // Imaginary part of a complex number
private static char jori = 'j'; // i or j in a + j.b or a + i.b representaion
// default value = j
private static boolean infOption = true; // option determinimg how infinity is handled
// if true (default option):
// multiplication with either complex number with either part = infinity returns infinity
// unless the one complex number is zero in both parts
// division by a complex number with either part = infinity returns zero
// unless the dividend is also infinite in either part
// if false:
// standard arithmetic performed
/*********************************************************/
// CONSTRUCTORS
// default constructor - real and imag = zero
public Complex()
{
this.real = 0.0D;
this.imag = 0.0D;
}
// constructor - initialises both real and imag
public Complex(double real, double imag)
{
this.real = real;
this.imag = imag;
}
// constructor - initialises real, imag = 0.0
public Complex(double real)
{
this.real = real;
this.imag = 0.0D;
}
// constructor - initialises both real and imag to the values of an existing Complex
public Complex(Complex c)
{
this.real = c.real;
this.imag = c.imag;
}
/*********************************************************/
// PUBLIC METHODS
// SET VALUES
// Set the value of real
public void setReal(double real){
this.real = real;
}
// Set the value of imag
public void setImag(double imag){
this.imag = imag;
}
// Set the values of real and imag
public void reset(double real, double imag){
this.real = real;
this.imag = imag;
}
// Set real and imag given the modulus and argument (in radians)
public void polar(double mod, double arg){
this.real = mod*Math.cos(arg);
this.imag = mod*Math.sin(arg);
}
// GET VALUES
// Get the value of real
public double getReal(){
return real;
}
// Get the value of imag
public double getImag(){
return imag;
}
// INPUT AND OUTPUT
// READ A COMPLEX NUMBER
// Read a complex number from the keyboard console after a prompt message
// in a String format compatible with Complex.parse,
// e.g 2+j3, 2 + j3, 2+i3, 2 + i3
// prompt = Prompt message to vdu
public static final synchronized Complex readComplex(String prompt)
{
int ch = ' ';
String cstring = "";
boolean done = false;
System.out.print(prompt + " ");
System.out.flush();
while (!done){
try{
ch = System.in.read();
if (ch < 0 || (char)ch == '\n')
done = true;
else
cstring = cstring + (char) ch;
}
catch(java.io.IOException e){
done = true;
}
}
return Complex.parseComplex(cstring);
}
// Read a complex number from the keyboard console after a prompt message (with String default option)
// in a String format compatible with Complex.parse,
// e.g 2+j3, 2 + j3, 2+i3, 2 + i3
// prompt = Prompt message to vdu
// dflt = default value
public static final synchronized Complex readComplex(String prompt, String dflt)
{
int ch = ' ';
String cstring = "";
boolean done = false;
System.out.print(prompt + " [default value = " + dflt + "] ");
System.out.flush();
int i=0;
while (!done){
try{
ch = System.in.read();
if (ch < 0 || (char)ch == '\n' || (char)ch =='\r'){
if(i==0){
cstring = dflt;
if((char)ch == '\r')ch = System.in.read();
}
done = true;
}
else{
cstring = cstring + (char) ch;
i++;
}
}
catch(java.io.IOException e){
done = true;
}
}
return Complex.parseComplex(cstring);
}
// Read a complex number from the keyboard console after a prompt message (with Complex default option)
// in a String format compatible with Complex.parse,
// e.g 2+j3, 2 + j3, 2+i3, 2 + i3
// prompt = Prompt message to vdu
// dflt = default value
public static final synchronized Complex readComplex(String prompt, Complex dflt)
{
int ch = ' ';
String cstring = "";
boolean done = false;
System.out.print(prompt + " [default value = " + dflt + "] ");
System.out.flush();
int i=0;
while (!done){
try{
ch = System.in.read();
if (ch < 0 || (char)ch == '\n' || (char)ch =='\r'){
if(i==0){
if((char)ch == '\r')ch = System.in.read();
return dflt;
}
done = true;
}
else{
cstring = cstring + (char) ch;
i++;
}
}
catch(java.io.IOException e){
done = true;
}
}
return Complex.parseComplex(cstring);
}
// Read a complex number from the keyboard console without a prompt message
// in a String format compatible with Complex.parse,
// e.g 2+j3, 2 + j3, 2+i3, 2 + i3
// prompt = Prompt message to vdu
public static final synchronized Complex readComplex()
{
int ch = ' ';
String cstring = "";
boolean done = false;
System.out.print(" ");
System.out.flush();
while (!done){
try{
ch = System.in.read();
if (ch < 0 || (char)ch == '\n')
done = true;
else
cstring = cstring + (char) ch;
}
catch(java.io.IOException e){
done = true;
}
}
return Complex.parseComplex(cstring);
}
//PRINT A COMPLEX NUMBER
// Print to terminal window with text (message) and a line return
public void println(String message){
System.out.println(message + " " + this.toString());
}
// Print to terminal window without text (message) but with a line return
public void println(){
System.out.println(" " + this.toString());
}
// Print to terminal window with text (message) but without line return
public void print(String message){
System.out.print(message + " " + this.toString());
}
// Print to terminal window without text (message) and without line return
public void print(){
System.out.print(" " + this.toString());
}
// PRINT AN ARRAY OF COMLEX NUMBERS
// Print an array to terminal window with text (message) and a line return
public static void println(String message, Complex[] aa){
System.out.println(message);
for(int i=0; i<aa.length; i++){
System.out.println(aa[i].toString());
}
}
// Print an array to terminal window without text (message) but with a line return
public static void println(Complex[] aa){
for(int i=0; i<aa.length; i++){
System.out.println(aa[i].toString());
}
}
// Print an array to terminal window with text (message) but no line returns except at the end
public static void print(String message, Complex[] aa){
System.out.print(message+ " ");
for(int i=0; i<aa.length; i++){
System.out.print(aa[i].toString() + " ");
}
System.out.println();
}
// Print an array to terminal window without text (message) but with no line returns except at the end
public static void print(Complex[] aa){
for(int i=0; i<aa.length; i++){
System.out.print(aa[i].toString());
}
System.out.println();
}
// TRUNCATION
// Rounds the mantissae of both the real and imaginary parts of Complex to prec places
// Static method
public static Complex truncate(Complex x, int prec){
if(prec<0)return x;
double xR = x.getReal();
double xI = x.getImag();
Complex y = new Complex();
xR = Fmath.truncate(xR, prec);
xI = Fmath.truncate(xI, prec);
y.reset(xR, xI);
return y;
}
// instance method
public Complex truncate(int prec){
if(prec<0)return this;
double xR = this.getReal();
double xI = this.getImag();
Complex y = new Complex();
xR = Fmath.truncate(xR, prec);
xI = Fmath.truncate(xI, prec);
y.reset(xR, xI);
return y;
}
// CONVERSIONS
// Format a complex number as a string, a + jb or a + ib[instance method]
// < value of real > < + or - > < j or i> < value of imag >
// Choice of j or i is set by Complex.seti() or Complex.setj()
// j is the default option for j or i
// Overides java.lang.String.toString()
public String toString(){
char ch='+';
if(this.imag<0.0D)ch='-';
return this.real+" "+ch+" "+jori+Math.abs(this.imag);
}
// Format a complex number as a string, a + jb or a + ib [static method]
// See static method above for comments
public static String toString(Complex aa){
char ch='+';
if(aa.imag<0.0D)ch='-';
return aa.real+" "+ch+jori+Math.abs(aa.imag);
}
// Sets the representation of the square root of minus one to j in Strings
public static void setj(){
jori = 'j';
}
// Sets the representation of the square root of minus one to i in Strings
public static void seti(){
jori = 'i';
}
// Returns the representation of the square root of minus one (j or i) set for Strings
public static char getjori(){
return jori;
}
// Parse a string to obtain Complex
// accepts strings 'real''s''sign''s''x''imag' and 'real''s''sign''s''x''.''imag'
// where x may be i or j and s may be no spaces or any number of spaces
// and sign may be + or -
// e.g. 2+j3, 2 + j3, 2+i3, 2 + i3
public static Complex parseComplex(String ss){
Complex aa = new Complex();
int i = ss.indexOf('j');
if(i==-1){
i = ss.indexOf('i');
}
if(i==-1)throw new NumberFormatException("no i or j found");
int imagSign=1;
int j = ss.indexOf('+');
if(j==-1){
j = ss.indexOf('-');
if(j>-1) imagSign=-1;
}
if(j==-1)throw new NumberFormatException("no + or - found");
int r0=0;
int r1=j;
int i0=i+1;
int i1=ss.length();
String sreal=ss.substring(r0,r1);
String simag=ss.substring(i0,i1);
aa.real=Double.parseDouble(sreal);
aa.imag=imagSign*Double.parseDouble(simag);
return aa;
}
// Same method as parseComplex
// Overides java.lang.Object.valueOf()
public static Complex valueOf(String ss){
return Complex.parseComplex(ss);
}
// Return a HASH CODE for the Complex number
// Overides java.lang.Object.hashCode()
public int hashCode()
{
long lreal = Double.doubleToLongBits(this.real);
long limag = Double.doubleToLongBits(this.imag);
int hreal = (int)(lreal^(lreal>>>32));
int himag = (int)(limag^(limag>>>32));
return 7*(hreal/10)+3*(himag/10);
}
// ARRAYS
// Create a one dimensional array of Complex objects of length n
// all real = 0 and all imag = 0
public static Complex[] oneDarray(int n){
Complex[] a =new Complex[n];
for(int i=0; i<n; i++){
a[i]=Complex.zero();
}
return a;
}
// Create a one dimensional array of Complex objects of length n
// all real = a and all imag = b
public static Complex[] oneDarray(int n, double a, double b){
Complex[] c =new Complex[n];
for(int i=0; i<n; i++){
c[i]=Complex.zero();
c[i].reset(a, b);
}
return c;
}
// Create a one dimensional array of Complex objects of length n
// all = the Complex constant
public static Complex[] oneDarray(int n, Complex constant){
Complex[] c =new Complex[n];
for(int i=0; i<n; i++){
c[i]=Complex.copy(constant);
}
return c;
}
// Create a two dimensional array of Complex objects of dimensions n and m
// all real = zero and all imag = zero
public static Complex[][] twoDarray(int n, int m){
Complex[][] a =new Complex[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
a[i][j]=Complex.zero();
}
}
return a;
}
// Create a two dimensional array of Complex objects of dimensions n and m
// all real = a and all imag = b
public static Complex[][] twoDarray(int n, int m, double a, double b){
Complex[][] c =new Complex[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
c[i][j]=Complex.zero();
c[i][j].reset(a, b);
}
}
return c;
}
// Create a two dimensional array of Complex objects of dimensions n and m
// all = the Complex constant
public static Complex[][] twoDarray(int n, int m, Complex constant){
Complex[][] c =new Complex[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
c[i][j]=Complex.copy(constant);
}
}
return c;
}
// COPY
// Copy a single complex number [static method]
public static Complex copy(Complex a){
if(a==null){
return null;
}
else{
Complex b = new Complex();
b.real=a.real;
b.imag=a.imag;
return b;
}
}
// Copy a single complex number [instance method]
public Complex copy(){
if(this==null){
return null;
}
else{
Complex b = new Complex();
b.real=this.real;
b.imag=this.imag;
return b;
}
}
// Copy a 1D array of complex numbers (deep copy)
// static metod
public static Complex[] copy(Complex[] a){
if(a==null){
return null;
}
else{
int n =a.length;
Complex[] b = Complex.oneDarray(n);
for(int i=0; i<n; i++){
b[i]=Complex.copy(a[i]);
}
return b;
}
}
// Copy a 2D array of complex numbers (deep copy)
public static Complex[][] copy(Complex[][] a){
if(a==null){
return null;
}
else{
int n =a.length;
int m =a[0].length;
Complex[][] b = Complex.twoDarray(n, m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
b[i][j]=Complex.copy(a[i][j]);
}
}
return b;
}
}
// CLONE
// Overrides Java.Object method clone
// Copy a single complex number [instance method]
public Object clone(){
if(this==null){
return null;
}
else{
Complex b = new Complex();
b.real=this.real;
b.imag=this.imag;
return (Object)b;
}
}
// ADDITION
// Add two Complex numbers [static method]
public static Complex plus(Complex a, Complex b){
Complex c = new Complex();
c.real=a.real+b.real;
c.imag=a.imag+b.imag;
return c;
}
//Add a double to a Complex number [static method]
public static Complex plus(Complex a, double b){
Complex c = new Complex();
c.real=a.real+b;
c.imag=a.imag;
return c;
}
//Add a Complex number to a double [static method]
public static Complex plus(double a, Complex b){
Complex c = new Complex();
c.real=a+b.real;
c.imag=b.imag;
return c;
}
//Add a double number to a double and return sum as Complex [static method]
public static Complex plus(double a, double b){
Complex c = new Complex();
c.real=a+b;
c.imag=0.0D;
return c;
}
//Add a Complex number to this Complex number [instance method]
// this Complex number remains unaltered
public Complex plus(Complex a ){
Complex b = new Complex();
b.real=this.real + a.real;
b.imag=this.imag + a.imag;
return b;
}
//Add double number to this Complex number [instance method]
// this Complex number remains unaltered
public Complex plus(double a ){
Complex b = new Complex();
b.real = this.real + a;
b.imag = this.imag;
return b;
}
//Add a Complex number to this Complex number and replace this with the sum
public void plusEquals(Complex a ){
this.real+=a.real;
this.imag+=a.imag;
}
//Add double number to this Complex number and replace this with the sum
public void plusEquals(double a ){
this.real+=a;
this.imag=this.imag;
}
// SUBTRACTION
//Subtract two Complex numbers [static method]
public static Complex minus (Complex a, Complex b){
Complex c = new Complex();
c.real=a.real-b.real;
c.imag=a.imag-b.imag;
return c;
}
//Subtract a double from a Complex number [static method]
public static Complex minus(Complex a, double b){
Complex c = new Complex();
c.real=a.real-b;
c.imag=a.imag;
return c;
}
//Subtract a Complex number from a double [static method]
public static Complex minus(double a, Complex b){
Complex c = new Complex();
c.real=a-b.real;
c.imag=-b.imag;
return c;
}
//Subtract a double number to a double and return difference as Complex [static method]
public static Complex minus(double a, double b){
Complex c = new Complex();
c.real=a-b;
c.imag=0.0D;
return c;
}
//Subtract a Complex number from this Complex number [instance method]
// this Complex number remains unaltered
public Complex minus(Complex a ){
Complex b = new Complex();
b.real=this.real-a.real;
b.imag=this.imag-a.imag;
return b;
}
//Subtract a double number from this Complex number [instance method]
// this Complex number remains unaltered
public Complex minus(double a ){
Complex b = new Complex();
b.real=this.real-a;
b.imag=this.imag;
return b;
}
//Subtract this Complex number from a double number [instance method]
// this Complex number remains unaltered
public Complex transposedMinus(double a ){
Complex b = new Complex();
b.real=a - this.real;
b.imag=this.imag;
return b;
}
//Subtract a Complex number from this Complex number and replace this by the difference
public void minusEquals(Complex a ){
this.real-=a.real;
this.imag-=a.imag;
}
//Subtract a double number from this Complex number and replace this by the difference
public void minusEquals(double a ){
this.real-=a;
this.imag=this.imag;
}
// MULTIPLICATION
// Sets the infinity handling option in multiplication and division
// infOption -> true; standard arithmetic overriden - see above (instance variable definitions) for details
// infOption -> false: standard arithmetic used
public static void setInfOption(boolean infOpt){
Complex.infOption = infOpt;
}
// Sets the infinity handling option in multiplication and division
// opt = 0: infOption -> true; standard arithmetic overriden - see above (instance variable definitions) for details
// opt = 1: infOption -> false: standard arithmetic used
public static void setInfOption(int opt){
if(opt<0 || opt>1)throw new IllegalArgumentException("opt must be 0 or 1");
Complex.infOption = true;
if(opt==1)Complex.infOption = false;
}
// Gets the infinity handling option in multiplication and division
// infOption -> true; standard arithmetic overriden - see above (instance variable definitions) for details
// infOption -> false: standard arithmetic used
public static boolean getInfOption(){
return Complex.infOption;
}
//Multiply two Complex numbers [static method]
public static Complex times(Complex a, Complex b){
Complex c = new Complex(0.0D, 0.0D);
if(Complex.infOption){
if(a.isInfinite() && !b.isZero()){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
if(b.isInfinite() && !a.isZero()){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
}
c.real=a.real*b.real-a.imag*b.imag;
c.imag=a.real*b.imag+a.imag*b.real;
return c;
}
//Multiply a Complex number by a double [static method]
public static Complex times(Complex a, double b){
Complex c = new Complex();
if(Complex.infOption){
if(a.isInfinite() && b!=0.0D){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
if(Fmath.isInfinity(b) && !a.isZero()){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
}
c.real=a.real*b;
c.imag=a.imag*b;
return c;
}
//Multiply a double by a Complex number [static method]
public static Complex times(double a, Complex b){
Complex c = new Complex();
if(Complex.infOption){
if(b.isInfinite() && a!=0.0D){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
if(Fmath.isInfinity(a) && !b.isZero()){
c.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return c;
}
}
c.real=a*b.real;
c.imag=a*b.imag;
return c;
}
//Multiply a double number to a double and return product as Complex [static method]
public static Complex times(double a, double b){
Complex c = new Complex();
c.real=a*b;
c.imag=0.0D;
return c;
}
//Multiply this Complex number by a Complex number [instance method]
// this Complex number remains unaltered
public Complex times(Complex a){
Complex b = new Complex();
if(Complex.infOption){
if(this.isInfinite() && !a.isZero()){
b.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return b;
}
if(a.isInfinite() && !this.isZero()){
b.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return b;
}
}
b.real=this.real*a.real-this.imag*a.imag;
b.imag=this.real*a.imag+this.imag*a.real;
return b;
}
//Multiply this Complex number by a double [instance method]
// this Complex number remains unaltered
public Complex times(double a){
Complex b = new Complex();
if(Complex.infOption){
if(this.isInfinite() && a!=0.0D){
b.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return b;
}
if(Fmath.isInfinity(a) && !this.isZero()){
b.reset(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
return b;
}
}
b.real=this.real*a;
b.imag=this.imag*a;
return b;
}
//Multiply this Complex number by a Complex number and replace this by the product
public void timesEquals(Complex a){
Complex b = new Complex();
boolean test = true;
if(Complex.infOption){
if((this.isInfinite() && !a.isZero()) || (a.isInfinite() && !this.isZero())){
this.real = Double.POSITIVE_INFINITY;
this.imag = Double.POSITIVE_INFINITY;
test = false;
}
}
if(test){
b.real=a.real*this.real-a.imag*this.imag;
b.imag=a.real*this.imag+a.imag*this.real;
this.real=b.real;
this.imag=b.imag;
}
}
//Multiply this Complex number by a double and replace this by the product
public void timesEquals(double a){
boolean test = true;
if(Complex.infOption){
if((this.isInfinite() && a!=0.0D) || (Fmath.isInfinity(a) && !this.isZero())){
this.real = Double.POSITIVE_INFINITY;
this.imag = Double.POSITIVE_INFINITY;
test = false;
}
}
if(test){
this.real=this.real*a;
this.imag=this.imag*a;
}
}
// DIVISION
//Division of two Complex numbers a/b [static method]
public static Complex over(Complex a, Complex b){
Complex c = new Complex(0.0D,0.0D);
if(Complex.infOption && !a.isInfinite() && b.isInfinite())return c;
double denom = 0.0D, ratio = 0.0D;
if(a.isZero()){
if(b.isZero()){
c.real=Double.NaN;
c.imag=Double.NaN;
}
else{
c.real=0.0D;
c.imag=0.0D;
}
}
else{
if(Math.abs(b.real)>=Math.abs(b.imag)){
ratio=b.imag/b.real;
denom=b.real+b.imag*ratio;
c.real=(a.real+a.imag*ratio)/denom;
c.imag=(a.imag-a.real*ratio)/denom;
}
else{
ratio=b.real/b.imag;
denom=b.real*ratio+b.imag;
c.real=(a.real*ratio+a.imag)/denom;
c.imag=(a.imag*ratio-a.real)/denom;
}
}
return c;
}
//Division of a Complex number, a, by a double, b [static method]
public static Complex over(Complex a, double b){
Complex c = new Complex(0.0D, 0.0D);
if(Complex.infOption && Fmath.isInfinity(b))return c;
c.real=a.real/b;
c.imag=a.imag/b;
return c;
}
//Division of a double, a, by a Complex number, b [static method]
public static Complex over(double a, Complex b){
Complex c = new Complex();
if(Complex.infOption && !Fmath.isInfinity(a) && b.isInfinite())return c;
double denom, ratio;
if(a==0.0D){
if(b.isZero()){
c.real=Double.NaN;
c.imag=Double.NaN;
}
else{
c.real=0.0D;
c.imag=0.0D;
}
}
else{
if(Math.abs(b.real)>=Math.abs(b.imag)){
ratio=b.imag/b.real;
denom=b.real+b.imag*ratio;
c.real=a/denom;
c.imag=-a*ratio/denom;
}
else{
ratio=b.real/b.imag;
denom=b.real*ratio+b.imag;
c.real=a*ratio/denom;
c.imag=-a/denom;
}
}
return c;
}
//Divide a double number by a double and return quotient as Complex [static method]
public static Complex over(double a, double b){
Complex c = new Complex();
c.real=a/b;
c.imag=0.0;
return c;
}
//Division of this Complex number by a Complex number [instance method]
// this Complex number remains unaltered
public Complex over(Complex a){
Complex b = new Complex(0.0D, 0.0D);
if(Complex.infOption && !this.isInfinite() && a.isInfinite())return b;
double denom = 0.0D, ratio = 0.0D;
if(Math.abs(a.real)>=Math.abs(a.imag)){
ratio=a.imag/a.real;
denom=a.real+a.imag*ratio;
b.real=(this.real+this.imag*ratio)/denom;
b.imag=(this.imag-this.real*ratio)/denom;
}
else
{
ratio=a.real/a.imag;
denom=a.real*ratio+a.imag;
b.real=(this.real*ratio+this.imag)/denom;
b.imag=(this.imag*ratio-this.real)/denom;
}
return b;
}
//Division of this Complex number by a double [instance method]
// this Complex number remains unaltered
public Complex over(double a){
Complex b = new Complex(0.0D, 0.0D);
b.real=this.real/a;
b.imag=this.imag/a;
return b;
}
//Division of a double by this Complex number [instance method]
// this Complex number remains unaltered
public Complex transposedOver(double a){
Complex c = new Complex(0.0D, 0.0D);
if(Complex.infOption && !Fmath.isInfinity(a) && this.isInfinite())return c;
double denom = 0.0D, ratio = 0.0D;
if(Math.abs(this.real)>=Math.abs(this.imag)){
ratio=this.imag/this.real;
denom=this.real+this.imag*ratio;
c.real=a/denom;
c.imag=-a*ratio/denom;
}
else
{
ratio=this.real/this.imag;
denom=this.real*ratio+this.imag;
c.real=a*ratio/denom;
c.imag=-a/denom;
}
return c;
}
//Division of this Complex number by a Complex number and replace this by the quotient
public void overEquals(Complex b){
Complex c = new Complex(0.0D, 0.0D);
boolean test = true;
if(Complex.infOption && !this.isInfinite() && b.isInfinite()){
this.real = 0.0D;
this.imag = 0.0D;
test=false;
}
if(test){
double denom = 0.0D, ratio = 0.0D;
if(Math.abs(b.real)>=Math.abs(b.imag)){
ratio=b.imag/b.real;
denom=b.real+b.imag*ratio;
c.real=(this.real+this.imag*ratio)/denom;
c.imag=(this.imag-this.real*ratio)/denom;
}
else
{
ratio=b.real/b.imag;
denom=b.real*ratio+b.imag;
c.real=(this.real*ratio+this.imag)/denom;
c.imag=(this.imag*ratio-this.real)/denom;
}
this.real = c.real;
this.imag = c.imag;
}
}
//Division of this Complex number by a double and replace this by the quotient
public void overEquals(double a){
this.real=this.real/a;
this.imag=this.imag/a;
}
// RECIPROCAL
// Returns the reciprocal (1/a) of a Complex number (a) [static method]
public static Complex inverse(Complex a){
Complex b = new Complex(0.0D, 0.0D);
if(Complex.infOption && a.isInfinite())return b;
b = Complex.over(1.0D, a);
return b;
}
// Returns the reciprocal (1/a) of a Complex number (a) [instance method]
public Complex inverse(){
Complex b = new Complex(0.0D, 0.0D);
b = Complex.over(1.0D, this);
return b;
}
//FURTHER MATHEMATICAL FUNCTIONS
// Negates a Complex number [static method]
public static Complex negate(Complex a){
Complex c = new Complex();
c.real=-a.real;
c.imag=-a.imag;
return c;
}
// Negates a Complex number [instance method]
public Complex negate(){
Complex c = new Complex();
c.real=-this.real;
c.imag=-this.imag;
return c;
}
//Absolute value (modulus) of a complex number [static method]
public static double abs(Complex a){
double rmod = Math.abs(a.real);
double imod = Math.abs(a.imag);
double ratio = 0.0D;
double res = 0.0D;
if(rmod==0.0D){
res=imod;
}
else{
if(imod==0.0D){
res=rmod;
}
if(rmod>=imod){
ratio=a.imag/a.real;
res=rmod*Math.sqrt(1.0D + ratio*ratio);
}
else{
ratio=a.real/a.imag;
res=imod*Math.sqrt(1.0D + ratio*ratio);
}
}
return res;
}
//Absolute value (modulus) of a complex number [instance method]
public double abs(){
double rmod = Math.abs(this.real);
double imod = Math.abs(this.imag);
double ratio = 0.0D;
double res = 0.0D;
if(rmod==0.0D){
res=imod;
}
else{
if(imod==0.0D){
res=rmod;
}
if(rmod>=imod){
ratio=this.imag/this.real;
res=rmod*Math.sqrt(1.0D + ratio*ratio);
}
else
{
ratio=this.real/this.imag;
res=imod*Math.sqrt(1.0D + ratio*ratio);
}
}
return res;
}
//Square of the absolute value (modulus) of a complex number [static method]
public static double squareAbs(Complex a){
return a.real*a.real + a.imag*a.imag;
}
//Square of the absolute value (modulus) of a complex number [instance method]
public double squareAbs(){
return this.real*this.real + this.imag*this.imag;
}
//Argument of a complex number [static method]
public static double arg(Complex a){
return Math.atan2(a.imag, a.real);
}
//Argument of a complex number [instance method]
public double arg(){
return Math.atan2(this.imag, this.real);
}
//Complex conjugate of a complex number [static method]
public static Complex conjugate(Complex a){
Complex c = new Complex();
c.real=a.real;
c.imag=-a.imag;
return c;
}
//Complex conjugate of a complex number [instance method]
public Complex conjugate(){
Complex c = new Complex();
c.real=this.real;
c.imag=-this.imag;
return c;
}
// Returns the length of the hypotenuse of a and b i.e. sqrt(abs(a)*abs(a)+abs(b)*abs(b))
// where a and b are Complex [without unecessary overflow or underflow]
public static double hypot(Complex aa, Complex bb){
double amod=Complex.abs(aa);
double bmod=Complex.abs(bb);
double cc = 0.0D, ratio = 0.0D;
if(amod==0.0D){
cc=bmod;
}
else{
if(bmod==0.0D){
cc=amod;
}
else{
if(amod>=bmod){
ratio=bmod/amod;
cc=amod*Math.sqrt(1.0 + ratio*ratio);
}
else{
ratio=amod/bmod;
cc=bmod*Math.sqrt(1.0 + ratio*ratio);
}
}
}
return cc;
}
//Exponential of a complex number
public static Complex exp(Complex aa){
Complex z = new Complex();
double a = aa.real;
double b = aa.imag;
if(b==0.0D){
z.real=Math.exp(a);
z.imag=0.0D;
}
else{
if(a==0D){
z.real=Math.cos(b);
z.imag=Math.sin(b);
}
else{
double c=Math.exp(a);
z.real=c*Math.cos(b);
z.imag=c*Math.sin(b);
}
}
return z;
}
//Exponential of a real number returned as a complex number
public static Complex exp(double aa){
Complex bb = new Complex(aa, 0.0D);
return Complex.exp(bb);
}
// Returns exp(j*arg) where arg is real (a double)
public static Complex expPlusJayArg(double arg){
Complex argc = new Complex(0.0D, arg);
return Complex.exp(argc);
}
// Returns exp(-j*arg) where arg is real (a double)
public static Complex expMinusJayArg(double arg){
Complex argc = new Complex(0.0D, -arg);
return Complex.exp(argc);
}
//Principal value of the natural log of an Complex number
public static Complex log(Complex aa ){
double a=aa.real;
double b=aa.imag;
Complex c = new Complex();
c.real=Math.log(Complex.abs(aa));
c.imag=Math.atan2(b,a);
return c;
}
//Roots
//Principal value of the square root of a complex number
public static Complex sqrt(Complex aa ){
double a=aa.real;
double b=aa.imag;
Complex c = new Complex();
if(b==0.0D){
if(a>=0.0D){
c.real=Math.sqrt(a);
c.imag=0.0D;
}
else{
c.real=0.0D;
c.imag= Math.sqrt(-a);
}
}
else{
double w, ratio;
double amod=Math.abs(a);
double bmod=Math.abs(b);
if(amod>=bmod){
ratio=b/a;
w=Math.sqrt(amod)*Math.sqrt(0.5D*(1.0D + Math.sqrt(1.0D + ratio*ratio)));
}
else{
ratio=a/b;
w=Math.sqrt(bmod)*Math.sqrt(0.5D*(Math.abs(ratio) + Math.sqrt(1.0D + ratio*ratio)));
}
if(a>=0.0){
c.real=w;
c.imag=b/(2.0D*w);
}
else{
if(b>=0.0){
c.imag=w;
c.real=bmod/(2.0D*c.imag);
}
else{
c.imag=-w;
c.real=bmod/(2.0D*c.imag);
}
}
}
return c;
}
//Principal value of the nth root of a complex number (n = integer > 1)
public static Complex nthRoot(Complex aa, int n ){
if(n==0)throw new ArithmeticException("Division by zero (n = 0 - infinite root) attempted in Complex.nthRoot");
double a=aa.real;
double b=aa.imag;
Complex c = new Complex();
double d=(double) n;
double r = Math.pow(Complex.abs(aa), 1.0D/d);
double theta = Math.atan2(b,a)/d;
c.real= r*Math.cos(theta);
c.imag= r*Math.sin(theta);
return c;
}
//Powers
// Square of a complex number
public static Complex square(Complex aa){
Complex c = new Complex();
c.real= aa.real*aa.real-aa.imag*aa.imag;
c.imag= 2.0D*aa.real*aa.imag;
return c;
}
// returns a Complex number raised to a Complex power
public static Complex pow(Complex a, Complex b ){
Complex c = new Complex();
c=Complex.exp(Complex.times(b, Complex.log(a)));
return c;
}
// returns a Complex number raised to a double power
public static Complex pow(Complex a, double b){
return powDouble(a, b);
}
// returns a Complex number raised to an integer, i.e. int, power
public static Complex pow(Complex a, int n ){
double b = (double) n;
return powDouble(a, b);
}
// returns a double raised to a Complex power
public static Complex pow(double a, Complex b ){
Complex c = new Complex();
double z = Math.pow(a, b.real);
c=Complex.exp(Complex.times(Complex.plusJay(), b.imag*Math.log(a)));
c=Complex.times(z, c);
return c;
}
// Complex trigonometric functions
//Sine of an Complex number
public static Complex sin(Complex aa ){
Complex c = new Complex();
double a = aa.real;
double b = aa.imag;
c.real = Math.sin(a)*Fmath.cosh(b);
c.imag = Math.cos(a)*Fmath.sinh(b);
return c;
}
//Cosine of an Complex number
public static Complex cos(Complex aa ){
Complex c = new Complex();
double a = aa.real;
double b = aa.imag;
c.real= Math.cos(a)*Fmath.cosh(b);
c.imag= -Math.sin(a)*Fmath.sinh(b);
return c;
}
//Tangent of an Complex number
public static Complex tan(Complex aa ){
Complex c = new Complex();
double denom = 0.0D;
double a = aa.real;
double b = aa.imag;
Complex x = new Complex(Math.sin(a)*Fmath.cosh(b), Math.cos(a)*Fmath.sinh(b));
Complex y = new Complex(Math.cos(a)*Fmath.cosh(b), -Math.sin(a)*Fmath.sinh(b));
c=Complex.over(x, y);
return c;
}
//Hyperbolic sine of a Complex number
public static Complex sinh(Complex a ){
Complex c = new Complex();
c=a.times(plusJay());
c=(Complex.minusJay()).times(Complex.sin(c));
return c;
}
//Hyperbolic cosine of a Complex number
public static Complex cosh(Complex a ){
Complex c = new Complex();
c=a.times(Complex.plusJay());
c=Complex.cos(c);
return c;
}
//Hyperbolic tangent of a Complex number
public static Complex tanh(Complex a ){
Complex c = new Complex();
c = (Complex.sinh(a)).over(Complex.cosh(a));
return c;
}
//Inverse sine of a Complex number
public static Complex asin(Complex a ){
Complex c = new Complex();
c=Complex.sqrt(Complex.minus(1.0D, Complex.square(a)));
c=(Complex.plusJay().times(a)).plus(c);
c=Complex.minusJay().times(Complex.log(c));
return c;
}
//Inverse cosine of a Complex number
public static Complex acos(Complex a ){
Complex c = new Complex();
c=Complex.sqrt(minus(Complex.square(a),1.0));
c=a.plus(c);
c=Complex.minusJay().times(Complex.log(c));
return c;
}
//Inverse tangent of a Complex number
public static Complex atan(Complex a ){
Complex c = new Complex();
Complex d = new Complex();
c=Complex.plusJay().plus(a);
d=Complex.plusJay().minus(a);
c=c.over(d);
c=Complex.log(c);
c=Complex.plusJay().times(c);
c=c.over(2.0D);
return c;
}
//Inverse hyperbolic sine of a Complex number
public static Complex asinh(Complex a ){
Complex c = new Complex(0.0D, 0.0D);
c=Complex.sqrt(Complex.square(a).plus(1.0D));
c=a.plus(c);
c=Complex.log(c);
return c;
}
//Inverse hyperbolic cosine of a Complex number
public static Complex acosh(Complex a ){
Complex c = new Complex();
c=Complex.sqrt(Complex.square(a).minus(1.0D));
c=a.plus(c);
c=Complex.log(c);
return c;
}
//Inverse hyperbolic tangent of a Complex number
public static Complex atanh(Complex a ){
Complex c = new Complex();
Complex d = new Complex();
c=Complex.plusOne().plus(a);
d=Complex.plusOne().minus(a);
c=c.over(d);
c=Complex.log(c);
c=c.over(2.0D);
return c;
}
// LOGICAL FUNCTIONS
// Returns true if the Complex number has a zero imaginary part, i.e. is a real number
public static boolean isReal(Complex a){
boolean test = false;
if(a.imag==0.0D)test = true;
return test;
}
public boolean isReal(){
boolean test = false;
if(Math.abs(this.imag)==0.0D)test = true;
return test;
}
// Returns true if the Complex number has a zero real and a zero imaginary part
// i.e. has a zero modulus
public static boolean isZero(Complex a){
boolean test = false;
if(Math.abs(a.real)==0.0D && Math.abs(a.imag)==0.0D)test = true;
return test;
}
public boolean isZero(){
boolean test = false;
if(Math.abs(this.real)==0.0D && Math.abs(this.imag)==0.0D)test = true;
return test;
}
// Returns true if either the real or the imaginary part of the Complex number
// is equal to plus infinity
public boolean isPlusInfinity(){
boolean test = false;
if(this.real==Double.POSITIVE_INFINITY || this.imag==Double.POSITIVE_INFINITY)test = true;
return test;
}
public static boolean isPlusInfinity(Complex a){
boolean test = false;
if(a.real==Double.POSITIVE_INFINITY || a.imag==Double.POSITIVE_INFINITY)test = true;
return test;
}
// Returns true if either the real or the imaginary part of the Complex number
// is equal to minus infinity
public boolean isMinusInfinity(){
boolean test = false;
if(this.real==Double.NEGATIVE_INFINITY || this.imag==Double.NEGATIVE_INFINITY)test = true;
return test;
}
public static boolean isMinusInfinity(Complex a){
boolean test = false;
if(a.real==Double.NEGATIVE_INFINITY || a.imag==Double.NEGATIVE_INFINITY)test = true;
return test;
}
// Returns true if either the real or the imaginary part of the Complex number
// is equal to either infinity or minus plus infinity
public static boolean isInfinite(Complex a){
boolean test = false;
if(a.real==Double.POSITIVE_INFINITY || a.imag==Double.POSITIVE_INFINITY)test = true;
if(a.real==Double.NEGATIVE_INFINITY || a.imag==Double.NEGATIVE_INFINITY)test = true;
return test;
}
public boolean isInfinite(){
boolean test = false;
if(this.real==Double.POSITIVE_INFINITY || this.imag==Double.POSITIVE_INFINITY)test = true;
if(this.real==Double.NEGATIVE_INFINITY || this.imag==Double.NEGATIVE_INFINITY)test = true;
return test;
}
// Returns true if the Complex number is NaN (Not a Number)
// i.e. is the result of an uninterpretable mathematical operation
public static boolean isNaN(Complex a){
boolean test = false;
if(a.real!=a.real || a.imag!=a.imag)test = true;
return test;
}
public boolean isNaN(){
boolean test = false;
if(this.real!=this.real || this.imag!=this.imag)test = true;
return test;
}
// Returns true if two Complex number are identical
// Follows the Sun Java convention of treating all NaNs as equal
// i.e. does not satisfies the IEEE 754 specification
// but does let hashtables operate properly
public boolean equals(Complex a){
boolean test = false;
if(this.isNaN()&&a.isNaN()){
test=true;
}
else{
if(this.real == a.real && this.imag == a.imag)test = true;
}
return test;
}
public boolean isEqual(Complex a){
boolean test = false;
if(this.isNaN()&&a.isNaN()){
test=true;
}
else{
if(this.real == a.real && this.imag == a.imag)test = true;
}
return test;
}
public static boolean isEqual(Complex a, Complex b){
boolean test = false;
if(isNaN(a)&&isNaN(b)){
test=true;
}
else{
if(a.real == b.real && a.imag == b.imag)test = true;
}
return test;
}
// returns true if the differences between the real and imaginary parts of two complex numbers
// are less than fract times the larger real and imaginary part
public boolean equalsWithinLimits(Complex a, double fract){
return isEqualWithinLimits(a, fract);
}
public boolean isEqualWithinLimits(Complex a, double fract){
boolean test = false;
double rt = this.getReal();
double ra = a.getReal();
double it = this.getImag();
double ia = a.getImag();
double rdn = 0.0D;
double idn = 0.0D;
double rtest = 0.0D;
double itest = 0.0D;
if(rt==0.0D && it==0.0D && ra==0.0D && ia==0.0D)test=true;
if(!test){
rdn=Math.abs(rt);
if(Math.abs(ra)>rdn)rdn=Math.abs(ra);
if(rdn==0.0D){
rtest=0.0;
}
else{
rtest=Math.abs(ra-rt)/rdn;
}
idn=Math.abs(it);
if(Math.abs(ia)>idn)idn=Math.abs(ia);
if(idn==0.0D){
itest=0.0;
}
else{
itest=Math.abs(ia-it)/idn;
}
if(rtest<fract && itest<fract)test=true;
}
return test;
}
public static boolean isEqualWithinLimits(Complex a, Complex b, double fract){
boolean test = false;
double rb = b.getReal();
double ra = a.getReal();
double ib = b.getImag();
double ia = a.getImag();
double rdn = 0.0D;
double idn = 0.0D;
if(ra==0.0D && ia==0.0D && rb==0.0D && ib==0.0D)test=true;
if(!test){
rdn=Math.abs(rb);
if(Math.abs(ra)>rdn)rdn=Math.abs(ra);
idn=Math.abs(ib);
if(Math.abs(ia)>idn)idn=Math.abs(ia);
if(Math.abs(ra-rb)/rdn<fract && Math.abs(ia-ia)/idn<fract)test=true;
}
return test;
}
// SOME USEFUL NUMBERS
// returns the number zero (0) as a complex number
public static Complex zero(){
Complex c = new Complex();
c.real=0.0D;
c.imag=0.0D;
return c;
}
// returns the number one (+1) as a complex number
public static Complex plusOne(){
Complex c = new Complex();
c.real=1.0D;
c.imag=0.0D;
return c;
}
// returns the number minus one (-1) as a complex number
public static Complex minusOne(){
Complex c = new Complex();
c.real=-1.0D;
c.imag=0.0D;
return c;
}
// returns plus j
public static Complex plusJay(){
Complex c = new Complex();
c.real=0.0D;
c.imag=1.0D;
return c;
}
// returns minus j
public static Complex minusJay(){
Complex c = new Complex();
c.real=0.0D;
c.imag=-1.0D;
return c;
}
// returns pi as a Complex number
public static Complex pi(){
Complex c = new Complex();
c.real=Math.PI;
c.imag=0.0D;
return c;
}
// returns 2.pi.j
public static Complex twoPiJay(){
Complex c = new Complex();
c.real=0.0D;
c.imag=2.0D*Math.PI;
return c;
}
// PRIVATE METHODS
// returns a Complex number raised to a double power
// this method is used for calculation within this class file
// see above for corresponding public method
private static Complex powDouble(Complex a, double b){
Complex z = new Complex();
double re=a.real;
double im=a.imag;
if(im==0.0D){
z.real=Math.pow(re, b);
z.imag=0.0D;
}
else{
if(re==0.0D){
z=Complex.exp(Complex.times(b, Complex.log(a)));
}
else{
double c=Math.pow(re*re+im*im, b/2.0D);
double th=Math.atan2(im, re);
z.real=c*Math.cos(b*th);
z.imag=c*Math.sin(b*th);
}
}
return z;
}
}