RFR: 8377223: Port fdlibm atanh to Java
Anton Artemov
aartemov at openjdk.org
Wed Feb 18 11:32:22 UTC 2026
On Wed, 18 Feb 2026 10:10:31 GMT, Anton Artemov <aartemov at openjdk.org> wrote:
> Hi, please consider the following changes:
>
> This is a port of FDLIBM atanh method.
Original C vs transliteration port:
$ diff -w fdlib_atanh.c Atanh.translit.java
1c1,3
< /* __ieee754_atanh(x)
---
> /**
> * Return the Inverse Hyperbolic Tangent of x
> *
17a20,23
> private static final class Atanh {
> private static final double zero = 0.0;
> private static final double one = 1.0;
> private static final double huge = 1.0e300;
19,35c25
< #include "fdlibm.h"
<
< #ifdef __STDC__
< static const double one = 1.0, huge = 1e300;
< #else
< static double one = 1.0, huge = 1e300;
< #endif
<
< static double zero = 0.0;
<
< #ifdef __STDC__
< double __ieee754_atanh(double x)
< #else
< double __ieee754_atanh(x)
< double x;
< #endif
< {
---
> static double compute(double x) {
38c28
< unsigned lx;
---
> /*unsigned*/ int lx;
47c37
< __HI(x) = ix; /* x <- |x| */
---
> x = __HI(x, ix); /* x <- |x| */
53a44
> }
Transliteration vs more idiomatic port:
$ diff -w Atanh.translit.java Atanh.fdlibm.java
3d2
< *
5,9d3
< * 1.Reduced x to positive by atanh(-x) = -atanh(x)
< * 2.For x>=0.5
< * 1 2x x
< * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
< * 2 1 - x 1 - x
11,12d4
< * For x<0.5
< * atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
14,17c6,12
< * Special cases:
< * atanh(x) is NaN if |x| > 1 with signal;
< * atanh(NaN) is that NaN with no signal;
< * atanh(+-1) is +-INF with signal.
---
> * atanh(x) is defined so that atanh(tanh(alpha)) = alpha, -∞ < alpha < ∞
> * and tanh(atanh(x)) = x, -1 < x < 1;
> * It can be written as atanh(x) = 0.5 * log1p(2 * x/(1-x)), -1 < x < 1;
> * 1.
> * atanh(x) := 0.5 * log1p(2 * x/(1 - x)), if |x| >= 0.5,
> * := 0.5 * log1p(2x + 2x * x/(1 - x)), if |x| < 0.5.
> *
18a14,18
> *
> * Special cases:
> * only atanh(±0)=±0 is exact for finite x.
> * atanh(NaN) is NaN
> * atanh(±1) is ±∞
20c20
< private static final class Atanh {
---
> static final class Atanh {
31,32c31,32
< ix = hx&0x7fffffff;
< if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
---
> ix = hx & 0x7fff_ffff;
> if ((ix | ((lx | (-lx)) >> 31)) > 0x3ff0_0000) { /* |x| > 1 */
34c34,35
< if(ix==0x3ff00000)
---
> }
> if (ix == 0x3ff0_0000) {
36c37,40
< if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */
---
> }
> if (ix < 0x3e30_0000 && (huge + x) > zero) {
> return x; /* x<2**-28 */
> }
38c42
< if(ix<0x3fe00000) { /* x < 0.5 */
---
> if (ix < 0x3fe0_0000) { /* x < 0.5 */
40c44
< t = 0.5*log1p(t+t*x/(one-x));
---
> t = 0.5 * Log1p.compute(t + t*x/(one - x));
42,43c46,51
< t = 0.5*log1p((x+x)/(one-x));
< if(hx>=0) return t; else return -t;
---
> t = 0.5 * Log1p.compute((x + x)/(one - x));
> if (hx >= 0) {
> return t;
> } else {
> return -t;
> }
-------------
PR Comment: https://git.openjdk.org/jdk/pull/29782#issuecomment-3919911569
More information about the core-libs-dev
mailing list