Hi Volker,

On 9/16/2015 2:02 AM, Volker Simonis wrote:
Hi Joe,

nice clean-up! From a maintenance point of view the the old fdlibm has
been a burden and a constant source of warnings with newer compilers.

What about the final arrays in Pow.compute (BP, DP_H, DP_L). In the
Interpreter (and even in C2 without EscapeAnalysis) this will lead to
allocations every time the method is called. Making them static fields
of 'Pow' will help here. On the other hand, if the arrays are static
fields of 'Pow', C2 will not be able to directly use the constants but
will have to load them from the array. So altogether, your current
implementation is optimal with HotSpot (with EscapeAnalysis turned on
by default) but might not be the best for other VMs without
EscapaAnalysis.

Have you done any benchmarking which compares the new Java against the
old C implementation?



I don't have exact stats to share, but some quick benchmarks indicate it is noticeably faster, more than 10%. The less computation pow does in a given case, the faster the Java version should be since the Java -> C -> Java cost should roughly be fixed.

Once the code is fully in Java, I would expect further tweaks to refine the code. For example, the original FDLIM code used the idiom of pointer aliasing a two-element int array with a double. (This idiom was also the source of many of those compiler warnings ;-) We can't directly use that idiom in Java, but the early versions of the port were a close transliteration of the C sources with equivalent Java method calls. That still left the code as operating on 32-bit quantities or doing comparisons of the double value by looking at its 32 high-order bits. Many of those 32-bit operations were removed as the port progressed to use clearer (if not also faster) operations such as comparing 64-bit double values directly as 64-bit double values.

For example, to my eye I'd much rather read

 185             // Special value of x
 186             if (x_abs == 0.0 ||
 187                 x_abs == INFINITY ||
 188                 x_abs == 1.0) {
 189                 z = x_abs;                 // x is +/-0, +/-inf, +/-1
 190                 if (y < 0.0)
 191                     z = 1.0/z;     // z = (1/|x|)

where x_abs is a double holding the absolute value of x, than the original semantically equivalent original

 178     /* special value of x */
 179         if(lx==0) {
 180             if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
 181                 z = ax;                 /*x is +-0,+-inf,+-1*/
 182                 if(hy<0) z = one/z;     /* z = (1/|x|) */

where lx is the lower-order 32 bits of x and ix is the high-order 32 bits of x with the sign bit zeroed out.

The version sent out for review still has some remaining 32-bit centered operations and at least some of those could be eliminated.

Thanks,

-Joe

Reply via email to