Subject: [Fwd: Java Numerics Complex]

From: Ronald F Boisvert <[email-masked]>
Date: Mon, 15 Mar 1999 09:45:02 -0500

-------- Original Message --------
 Subject: Java Numerics Complex
    Date: Wed, 10 Mar 1999 16:01:06 -0500
    From: "Fred Klingener" <[email-masked]>
Reply-To: "Fred Klingener" <[email-masked]>
      To: <[email-masked]>, <[email-masked]>
      CC: "Fred Klingener" <[email-masked]>

 Dear Roldan and Ron, On http://math.nist.gov/javanumerics/issues.html#ComplexNumbers you state the
issue:

 Issue Complex numbers are extremely important for numerical computing and should be available in
       Java. Their use should be convenient and operations on them should be efficient as
       fundamental data types (e.g. double).
 and then you offer (just to reject it) Solution A:

 Solution A Create the obvious Complex class and make it a standard API.

       Pros This is easy to do and can be done immediately.

       Cons Leads to unreadable and inefficient code.
 I'm writing not to complain about your summary rejection of A (I've struggled with that mess in a
half a dozen languages, so I'm with you 100%), but to offer Solution A1.  I've only written toy
engineering problems in Java, but some of those toys needed complex numbers, so I wrote a kComplex
class (more out of ignorance and fear - ignorance of the inner workings of Java objects and fear of
crippling performance if I did something stupid).  kComplex is the 'obvious' complex class, except
that all arithmetic and function evaluation is done on a static HP-calculator-style stack. My
motivation, of course, was that I'm not James Gosling, and I don't work for NIST, but I needed a
package that I liked.

 Solution A1 Create the obvious kComplex class with a static calculator stack as part of a package.

        Pros This, too, is easy to do and can be done immediately. The code seems to be fairly
             economical with very little bloat, compared to my version of Solution A.  For the
             math, complex numbers are always represented as two doubles for the real and imaginary
             parts.  Transformations to and from polar notation are done when pushing or popping
             the stack.  User source code, if a little stringy, is a decipherable list of
             operations. Instead of the desired overloaded C = A * exp(B), I have to
             write: enter(A);enter(B);exp();times();C = getX();

        Cons Whether or not this approach leads to unreadable code probably depends how much time
             the user has spent with HP calculators.  I've spent a lot of time with them, so I'm
             very comfortable writing and, later, reading the routines.  I haven't really stressed
             the idea on a real problem, so I don't know what kind of performance problems I'm
             going to find.  I know that my method call overhead will be fairly high, but I also
             know that I'll avoid all of the fear and doubt about newing and garbage collection I
             have with Solution A.  At least my implementations of Solution A.  A lot of my
             intermediate results are held in couple of static doubles.
 For your information, I'm attaching the Javadoc description of kComplex.  I'd rather not send you
my source for now, because it's untrapped, untested, unnclonable, unserializable and may contains
some truly embarrassing things.  Indeed, I think that I've spent more time on getting the Javadocs
ready than I have on the code. Of course, if you'd like to see it, I'd be happy to send it, as long
as you realize its limitations. kComplex is in the public domain. Sincerely, Fred KlingenerBrock
EngineeringRoxbury CT
All Packages Class Hierarchy This Package Previous Next Index

Class kMath.kComplex

Object
|
+----kMath.kComplex

public class kComplex

extends Object

The kComplex class is designed to enable, in Java,
engineering computations that use complex numbers. The class
has the following characteristics:

- Complex numbers are internally represented as double real
and imaginary parts.

- The class has a static Reverse Polish Notation HP-style
calculator XYZT + S stack. All math is performed on the stack
as doubles. Casting to and from other numeric representations,
if required, must be done as part of the stack 'push'
(enter()) or 'pop' (get*()) operations. The XYZT plus S stack
has a familiar complement of manipulation and access methods as
well as a set of static arithmetic and trancendental methods
that may be performed on the stack contents. As on the HP
calculators, monadic methods operate on the X register, and
dyadic methods operate on the X and Y registers. The single
storage register, S, may be used to save an intermediate result.
It communicates with the X register via the sto() and rcl() methods.

- Static void functions on the stack contents include:

-- arithmetic
o negation
o conjugate
o addition
o subtraction
o multiplication
o division

-- trancendental
o exponential
o logarithm
o integral power
o sine
o cosine
o hyperbolic sine
o hyperbolic cosine

Placed in the Public Domain by the author 12-17-98

Version:

0.0.0

12-17-98

Author:

Fred Klingener

Brock Engineering

Roxbury, CT

[email-masked]

I

Constant: Square root of -1

J

Constant: Square root of -1

kMath.kComplex(kComplex)

Constructs a kComplex, given a kComplex as a parameter

kMath.kComplex()

Constructs kComplex = (0.0d, 0.0d)

kMath.kComplex(double, double)

Constructs kComplex(re, im)

chs()

Stack math: Change sign

X <- (-X)

Y, Z, T unaffected

conjugate()

Stack math: Complex conjugate

X <- (complex conjugate of X)

Y, Z, T unaffected

cos()

Stack math: Cosine

X <- cos(X)

Y, Z, T unaffected

cosh()

Stack math: Hyperbolic Cosine

X <- cosh(X)

Y, Z, T unaffected

divide()

Stack math: Division X / Y

X <- (X / Y), Y <- Z, Z <- T, T <- T

enter()

Stack operation: Enter (rollup)

lost <- T, T <- Z, Z <- Y, Y <- X

X <- X

enter(kComplex)

Stack operation: Enter a complex into X

lost <- T, T <- Z, Z <- Y, Y <- X

X <- p

enter(double, double)

Stack operation: Enter a complex into X, given real and imaginary parts

lost <- T, T <- Z, Z <- Y, Y <- X

X <- a kComplex whose real and imaginary parts are the parameters

enterPolar(double, double)

Stack operation: Enter a complex into X, given magnitude and argument

lost <- T, T <- Z, Z <- Y, Y <- X

X <- a kComplex whose magnitude and argument are the parameters

exchXY()

Stack operation: Exchange
Enchange contents of X and Y
Z and T are unaffected

exp()

Stack math: Exponential

X <- (exp(X))

Y, Z, T unaffected

getArg()

Stack output: Returns the argument of X (in double radians)

getImaginary()

Stack output: Returns the imaginary part of X as a double

getMag()

Stack output: Returns the magnitude of X as a double

getReal()

Stack output: Returns the real part of X as a double

getX()

Stack output: Returns contents of X as a kComplex

log()

Stack math: Logarithm

X <- ln(X)

Y, Z, T unaffected

minus()

Stack math: Subtraction Y - X

X <- (Y - X)

Y <- Z, Z <- T, T <- T

plus()

Stack math: Addition X + Y

X <- (X + Y)

Y <- Z, Z <- T, T <- T

power(int)

Stack math: Power

X <- X^n (n integer)

Y, Z, T unaffected

rcl()

Storage operation: Recall

lost <- T, T <- Z, Z <- Y, Y <- X

X <- S

recip()

Stack math: Reciprocal

X <- 1/X

Y, Z, T unaffected

rolldown()

Stack operation: Rolldown

X <- Y, Y <- Z, Z <- T, T <- oldX

sin()

Stack math: Sine

X <- sin(X)

Y, Z, T unaffected

sinh()

Stack math: Hyperbolic Sine

X <- sinh(X)

Y, Z, T unaffected

sto()

Storage operation: Store

S <- X

stack unchanged

times()

Stack math: Multiplication X * Y

X <- (X * Y), Y <- Z, Z <- T, T <- T

I

public static final kMath.kComplex I

Constant: Square root of -1

J

public static final kMath.kComplex J

Constant: Square root of -1

kComplex

public kComplex(kComplex p)

Constructs a kComplex, given a kComplex as a parameter

kComplex

public kComplex()

Constructs kComplex = (0.0d, 0.0d)

kComplex

public kComplex(double re,
double im)

Constructs kComplex(re, im)

chs

public static void chs()

Stack math: Change sign

X <- (-X)

Y, Z, T unaffected

conjugate

public static void conjugate()

Stack math: Complex conjugate

X <- (complex conjugate of X)

Y, Z, T unaffected

cos

public static void cos()

Stack math: Cosine

X <- cos(X)

Y, Z, T unaffected

cosh

public static void cosh()

Stack math: Hyperbolic Cosine

X <- cosh(X)

Y, Z, T unaffected

divide

public static void divide()

Stack math: Division X / Y

X <- (X / Y), Y <- Z, Z <- T, T <- T

enter

public static void enter()

Stack operation: Enter (rollup)

lost <- T, T <- Z, Z <- Y, Y <- X

X <- X

enter

public static void enter(kComplex p)

Stack operation: Enter a complex into X

lost <- T, T <- Z, Z <- Y, Y <- X

X <- p

enter

public static void enter(double real,
double imaginary)

Stack operation: Enter a complex into X, given real and imaginary parts

lost <- T, T <- Z, Z <- Y, Y <- X

X <- a kComplex whose real and imaginary parts are the parameters

enterPolar

public static void enterPolar(double r,
double theta)

Stack operation: Enter a complex into X, given magnitude and argument

lost <- T, T <- Z, Z <- Y, Y <- X

X <- a kComplex whose magnitude and argument are the parameters

exchXY

public static void exchXY()

Stack operation: Exchange
Enchange contents of X and Y
Z and T are unaffected

exp

public static void exp()

Stack math: Exponential

X <- (exp(X))

Y, Z, T unaffected

getArg

public static double getArg()

Stack output: Returns the argument of X (in double radians)

getImaginary

public static double getImaginary()

Stack output: Returns the imaginary part of X as a double

getMag

public static double getMag()

Stack output: Returns the magnitude of X as a double

getReal

public static double getReal()

Stack output: Returns the real part of X as a double

getX

public static kMath.kComplex getX()

Stack output: Returns contents of X as a kComplex

log

public static void log()

Stack math: Logarithm

X <- ln(X)

Y, Z, T unaffected

minus

public static void minus()

Stack math: Subtraction Y - X

X <- (Y - X)

Y <- Z, Z <- T, T <- T

plus

public static void plus()

Stack math: Addition X + Y

X <- (X + Y)

Y <- Z, Z <- T, T <- T

power

public static void power(int n)

Stack math: Power

X <- X^n (n integer)

Y, Z, T unaffected

rcl

public static void rcl()

Storage operation: Recall

lost <- T, T <- Z, Z <- Y, Y <- X

X <- S

recip

public static void recip()

Stack math: Reciprocal

X <- 1/X

Y, Z, T unaffected

rolldown

public static void rolldown()

Stack operation: Rolldown

X <- Y, Y <- Z, Z <- T, T <- oldX

sin

public static void sin()

Stack math: Sine

X <- sin(X)

Y, Z, T unaffected

sinh

public static void sinh()

Stack math: Hyperbolic Sine

X <- sinh(X)

Y, Z, T unaffected

sto

public static void sto()

Storage operation: Store

S <- X

stack unchanged

times

public static void times()

Stack math: Multiplication X * Y

X <- (X * Y), Y <- Z, Z <- T, T <- T

All Packages Class Hierarchy This Package Previous Next Index