RFR: 8375285: Port fdlibm asinh to Java

Joe Darcy darcy at openjdk.org
Mon Jan 26 11:54:33 UTC 2026


On Fri, 16 Jan 2026 09:22:52 GMT, Anton Artemov <aartemov at openjdk.org> wrote:

> Hi, please consider the following changes:
> 
> This is a port of FDLIBM asinh method.
> 
> Original C vs transliteration port:
> 
> 
> $ diff -w fdlib_asinh.c Asinh.translit.java
> 1c1,3
> < /* asinh(x)
> ---
>> /**
>> * Return the Inverse Hyperbolic Sine of x
>> *
> 2a5
>> *
> 10a14,17
>> private static final class Asinh {
>>       private static final double one = 1.0;
>>       private static final double ln2 = 6.93147180559945286227e-01;
>>       private static final double huge = 1.0e300;
> 12,29c19
> < #include "fdlibm.h"
> <
> < #ifdef __STDC__
> < static const double
> < #else
> < static double
> < #endif
> < one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
> < ln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
> < huge=  1.00000000000000000000e+300;
> <
> < #ifdef __STDC__
> <       double asinh(double x)
> < #else
> <       double asinh(x)
> <       double x;
> < #endif
> < {
> ---
>>       static double compute(double x) {
> 39c29
> <           w = __ieee754_log(fabs(x))+ln2;
> ---
>>                       w = log(Math.abs(x))+ln2;
> 41,42c31,32
> <           t = fabs(x);
> <           w = __ieee754_log(2.0*t+one/(sqrt(x*x+one)+t));
> ---
>>                       t = Math.abs(x);
>>                       w = log(2.0*t+one/(sqrt(x*x+one)+t));
> 45c35
> <           w =log1p(fabs(x)+t/(one+sqrt(one+t)));
> ---
>>                       w =log1p(Math.abs(x)+t/(one+sqrt(one+t)));
> 47a38
>>       }
> 
> Transliteration port vs more idiomatic port:
> 
> 
> $ diff -w Asinh.translit.java Asinh.fdlibm.java
> 6,9c6,12
> < *  Based on
> < *    asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
> < *   we have
> < *   asinh(x) := x  if  1+x*x=1,
> ---
>>  *
>>  *      asinh(x) is defined so that asinh(sinh(alpha)) = alpha -INF < alpha < < INF
>>  *      and sinh(asinh(x)) = x, -INF < x  < INF.
>>  *      It can be written as asinh(x) = ln(x + sqrt(x^2 + 1)), -INF < x  < INF.
>>  *      1. Replace x by |x| as the function is odd.
>>  *      2.
>>  *          asinh(x) := x, if 1+x^2 = 1,
> 12a16,22
>>  *
>>  *
>>  *
>>  * Special cases:
>>  *      only asinh(0)=0 is exact for finite x.
>>  *      asinh(NaN) is NaN
>>  *      asinh(INF) is INF
> 14,15c24
> < private static final class Asinh {
> <       private static final double one = 1.0;
> ---
>> static final class Asinh {
> 24c33,35
> <               if(ix>=0x7ff00000) return x+x;  /* x is inf or NaN */
> ---
>>               if(ix >= 0x7ff00000) {
>>                       return x + x;                       /* x is inf or NaN */
>>               }
> 26c37,39
> <                       if(huge+x>one) return x;    /* return x inexact except 0...

src/java.base/share/classes/java/lang/FdLibm.java line 3543:

> 3541:             int hx,ix;
> 3542:             hx = __HI(x);
> 3543:             ix = hx&0x7fffffff;

As part of making the code more idiomatic, I would include adding space characters around `&` and switching one-line `/* ... */` over to `//` comments where possible.

src/java.base/share/classes/java/lang/Math.java line 2762:

> 2760: 
> 2761:     /**
> 2762:      * Returns the inverse hyperbolic sine of a {@code double} value.

The method specification should provide some general statements in term of the accuracy of the method in terms of ulps.

Explicitly specifying asinh(NaN) is NaN is probably worthwhile too.

src/java.base/share/classes/java/lang/StrictMath.java line 2173:

> 2171:     }
> 2172: 
> 2173:     /**

The list of "these methods must use FDLIBM algorithms..." up at the class-level specs of StrictMath should be updated to include asinh.

test/jdk/java/lang/StrictMath/HyperbolicTests.java line 497:

> 495:     private static int testAsinh() {
> 496:         int failures = 0;
> 497:         double [][] testCases = {

How were these values generated?

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/29273#discussion_r2719362250
PR Review Comment: https://git.openjdk.org/jdk/pull/29273#discussion_r2719360132
PR Review Comment: https://git.openjdk.org/jdk/pull/29273#discussion_r2719363829
PR Review Comment: https://git.openjdk.org/jdk/pull/29273#discussion_r2719365730


More information about the core-libs-dev mailing list