The method Complex::multiply(Complex) has the following check to recover
infinities:
double x = ac - bd;
double y = ad + bc;
if (Double.isNaN(a) && Double.isNaN(b)) {
The divide method checks x and y:
double x = Math.scalb( (a*c + b*d) / denom, -ilogbw);
double y = Math.scalb( (b*c - a*d) / denom, -ilogbw);
if (Double.isNaN(x) && Double.isNaN(y)) {
So the multiply method should be checking if x and y are NaN.
The multiply method also has this apparent cut-and-paste error:
a = Math.copySign(Double.isInfinite(a) ? 1.0 : 0.0, a);
b = Math.copySign(Double.isInfinite(a) ? 1.0 : 0.0, a);
where b should be assigned the sign from b not a.
I tried to find the C.99 standard for this as mentioned in the javadoc
and came up with this [1]. The implementation of multiply is provided on
page 470 and matches that in Complex without the afore mentioned bugs.
The definition for divide suggests switching from
!Double.isInfinite
to
Double.isFinite
which will return false for values that are NaN (where as
!Double.isInfinite will be true for NaN leading to an incorrect choice
in the algorithm).
The second correction statement is wrong:
} else if ((Double.isInfinite(a) && Double.isInfinite(b)) &&
!Double.isInfinite(c) && !Double.isInfinite(d)) {
should be:
} else if ((Double.isInfinite(a) || Double.isInfinite(b)) &&
!Double.isInfinite(c) && !Double.isInfinite(d)) {
The rest of divide is correct.
About isNaN:
"A complex or imaginary value with at least one infinite part is
regarded as an infinity
(even if its other part is a NaN). A complex or imaginary value is a
finite number if each
of its parts is a finite number (neither infinite nor NaN). A complex or
imaginary value is
a zero if each of its parts is a zero."
So Complex::isInfinite is defined correctly but Complex::isNaN does not
check if components are infinite, only if one of them is NaN. This means
you can be both infinite and NaN which does not seem correct.
This suggests updating isNaN to:
public boolean isNaN() {
return Double.isNaN(real) &&
Double.isNaN(imaginary);
}
I do not know how this will effect any computations that use isNaN().
The C.99 standard I found was a draft but the main host site states that
the working paper is the consolidated standard [2].
Any objections to updating multiply/divide/isNaN to match the standard?
I'll add unit tests to hit the edge cases that should fail with the
current implementation.
[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
[2] http://www.open-std.org/JTC1/SC22/WG14/www/standards
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]