In short: - Math.hypot is required in Complex to compute sqrt(x^2 + y^2) without over/underflow to 1 ULP precision. - Complex also requires the same computation without the sqrt or over/underflow protection - I found the reference for Math.hypot and reimplemented the function - My port is 4x faster than Math.hypot and the same accuracy (or better) - I will add this as a private internal method in Complex - The source for the port requires the original licence is maintained
The question is where to put the notice of the original license? Copying from commons RNG it would be in the source method javadoc and also in all LICENSE.txt files through the multi-module project. This seems excessive. I thought perhaps to include it only in numbers parent and then the complex module where it applies. Background The complex class uses the Math.hypot(double, double) function to determine the absolute value of a complex number x + iy as sqrt(x^2 + y^2) without over/underflow to 1 ULP precision. This is used directly (in sqrt() and abs()) but also without the square root to compute x^2 + y^2 in the log() function. These functions also perform over/underflow protection and so ideally just require access to the same formula for high precision x^2 + y^2. This would enable consistency across the different methods that use the absolute of the complex number. Currently the hypot function is very slow in the Complex JMH benchmark so I looked into hypot. This function is known to be slow [1] pre-Java 9 which I was using for benchmarking. I found that in Java 9 the code was changed from calling a native function to an implementation in Java of the "Freely Distributable Maths Library" [2]. The JMH benchmark for complex shows an improvement between Java 8 and 9 of about 7-fold speed increase. However this does not allow access to the same computation without the square root. The source code for fdlibm has a permission license [3] so I have implemented a port that allows separation of the x^2 + y^2 computation from the sqrt and the overflow protection. In testing my ported version I found cases where it was more accurate than the Java reference, but none where it was less accurate. I attribute this to the different implementation of splitting a number into parts for high precision that is different in my port from the original. I used the split that is already present in Complex. I tested side-by-side an alternative that was closer to the method from fdlibm and it was a bit slower (in Java) and the same accuracy as the JDK reference. So I assume that the JDK reference has stuck exactly to the fdlibm code. I also found my port to be 4x faster than the Java reference. This may require more investigation but for now I would like to put my port into Complex as an internal method. Note the method is different from the commons FastMath.hypot implementation which does not compute the result to 1 ULP. I will add this to the JMH benchmark for reference so we have Math.hypot, FastMath.hypot and the hypot method within Complex. The licence for fdlibm is shown in [3]. This states that code can be copied/modified as long as the original notice is maintained. In commons RNG the licence for the port of the MersenneTwister is placed in the Java source file and in all LICENSE.txt files through the multi-module project. So should I do the same for numbers or just put the license into the complex module? [1] https://stackoverflow.com/questions/3764978/why-hypot-function-is-so-slow <https://stackoverflow.com/questions/3764978/why-hypot-function-is-so-slow> [2] https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7130085 <https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7130085> [3] https://www.netlib.org/fdlibm/e_hypot.c <https://www.netlib.org/fdlibm/e_hypot.c>