> On 21 Dec 2019, at 11:42, Gilles Sadowski <gillese...@gmail.com> wrote:
> 
>> ...
> 
> So, would you suggest that no "Number"-like class should ever throw
> an exception (but instead return the equivalent of "Double.NaN”)?

Yes. As it was the method could throw for some invalid input and not others. 
This is inconsistent. Changing to return a NaN equivalent is more neutral. 
Through the rest of the code all the computations that may end up computing NaN 
just return NaN. There is no raising of exceptions even when the ISO C99 
standard states that an exception may be raised, i.e. these do not throw 
ArithmeticException. Removing all exceptions from the class could be stated as 
a design decision in the class javadoc. The only exceptions are from the 
parse(String) method.


I have been documenting the class using MathJax. This has raised a few more 
discrepancies with the c++ standards:

1. Static constructors

Complex:

ofCartesian(x, y)
ofPolar(rho, theta)

No public constructor.

C++

complex(x, y)         // This is a public class constructor for type <complex>
polar(rho, theta)

Should we change to the same name, add synonyms or just accept the API 
difference?

Sticking to the VALJO design would leave it as is and document that ofPolar 
matches the functionality of the ISO C++ polar method.


2. Reciprocal

I had to change the implementation of reciprocal to call divide, effectively:

Complex.ONE.divide(this)

This uses scaling for the divisor and can compute values that the previous 
version could not such as:

Complex.ofCartesian(Double.MAX_VALUE, Double.MAX_VALUE).reciprocal()

It also better handles NaN and infinite edge cases.


This method seems redundant. The origin in CM3 was due to Complex implementing 
the FieldElement interface. This has reciprocal() as a required method. 

It also has multiply(int) hence why that method was originally in the numbers 
version of Complex. This has now been dropped as it is redundant with 
multiply(double). Since we do not have to support the FieldElement interface I 
would suggest dropping reciprocal as well.


3. Equals

Why are there so many static equals functions using 
o.a.c.numbers.core.Precision with ULP and deltas?

boolean equals(Complex x, Complex y, int maxUlps)

@return {@code true} if there are fewer than {@code maxUlps} floating
     * point values between the real or imaginary, respectively, parts of 
{@code x}
     * and {@code y}.


boolean equals(Complex x, Complex y)

@return equals(x, y, 1)


boolean equals(Complex x, Complex y, double eps)

@return {@code true} if the values are two adjacent floating point
     * numbers or they are within range of each other.


boolean equalsWithRelativeTolerance(Complex x, Complex y,  double eps)

{@code true} if the values are two adjacent floating point
     * numbers or they are within range of each other.


These are all helper methods. None are required for the test suite. I do not 
see the need to have them in the core Complex class. The methods do not cover 
all possible ways to measure equality, just some using the Precision class. I 
would drop these and leave it to a user to decide how to measure equality. 

However I do note that similar methods are in the CM3 Complex class. Leaving 
them here would make porting to numbers easy. I think that before the 1.0 
release  is the time to decide if they should be maintained in Complex, in 
another class such as ComplexPrecision for legacy support of porting from CM3, 
or dropped. In the later case a note could be added to the package javadoc to 
state how to replicate the equals functionality from CM3 using 
numbers.Precision.

Alex





---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to