Initial pass of porting FDLIBM sinh/cosh/tanh to Java. I do intend to refactor the regression tests a bit to reduce duplication, but the actual ports should be ready for review.
Diff'ing the ports as before, original vs transliteration port: $ diff -w Hyperbolic.c Hyperbolic.translit.java 1c1 < /* __ieee754_sinh(x) --- > /** 17a18,19 > static class Sinh { > private static final double one = 1.0, shuge = 1.0e307; 19,33c21 < #include "fdlibm.h" < < #ifdef __STDC__ < static const double one = 1.0, shuge = 1.0e307; < #else < static double one = 1.0, shuge = 1.0e307; < #endif < < #ifdef __STDC__ < double __ieee754_sinh(double x) < #else < double __ieee754_sinh(x) < double x; < #endif < { --- > private static double compute(double x) { 36c24 < unsigned lx; --- > /* unsigned */ int lx; 51c39 < t = expm1(fabs(x)); --- > t = FdlibmTranslit.expm1(Math.abs(x)); 57c45 < if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x)); --- > if (ix < 0x40862E42) return h*StrictMath.exp(Math.abs(x)); // > TODO switch to translit 60,62c48,52 < lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); < if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d))) { < w = __ieee754_exp(0.5*fabs(x)); --- > // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); > // lx = (((*(unsigned*)&one)>>29)) + (unsigned*)&x ; > lx = __LO(x); > if (ix<0x408633CE || ((ix==0x408633ce)&&(Long.compareUnsigned(lx, > 0x8fb9f87d) <= 0 ))) { > w = StrictMath.exp(0.5*Math.abs(x)); // TODO switch to > translit 70c60,62 < /* __ieee754_cosh(x) --- > } > > /** 90,105c82,84 < < #include "fdlibm.h" < < #ifdef __STDC__ < static const double one = 1.0, half=0.5, huge = 1.0e300; < #else < static double one = 1.0, half=0.5, huge = 1.0e300; < #endif < < #ifdef __STDC__ < double __ieee754_cosh(double x) < #else < double __ieee754_cosh(x) < double x; < #endif < { --- > static class Cosh { > private static final double one = 1.0, half=0.5, huge = 1.0e300; > private static double compute(double x) { 108c87 < unsigned lx; --- > /*unsigned*/ int lx; 119c98 < t = expm1(fabs(x)); --- > t = expm1(Math.abs(x)); 127c106 < t = __ieee754_exp(fabs(x)); --- > t = StrictMath.exp(Math.abs(x)); // TODO switch to translit 132c111 < if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x)); --- > if (ix < 0x40862E42) return half*StrictMath.exp(Math.abs(x)); // > TODO switch to translit 135c114 < lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); --- > lx = __LO(x); 137,138c116,117 < ((ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d))) { < w = __ieee754_exp(half*fabs(x)); --- > ((ix==0x408633ce)&&(Integer.compareUnsigned(lx, 0x8fb9f87d) > <= 0))) { > w = StrictMath.exp(half*Math.abs(x)); // TODO switch to > translit 146c125,127 < /* Tanh(x) --- > } > > /** 169,184c150,152 < < #include "fdlibm.h" < < #ifdef __STDC__ < static const double one=1.0, two=2.0, tiny = 1.0e-300; < #else < static double one=1.0, two=2.0, tiny = 1.0e-300; < #endif < < #ifdef __STDC__ < double tanh(double x) < #else < double tanh(x) < double x; < #endif < { --- > static class Tanh { > private static final double one=1.0, two=2.0, tiny = 1.0e-300; > static double compute(double x) { 203c171 < t = expm1(two*fabs(x)); --- > t = expm1(two*Math.abs(x)); 206c174 < t = expm1(-two*fabs(x)); --- > t = expm1(-two*Math.abs(x)); 214a183 > } Note that the original has a in-line version of the "__LO" macro rather than using the macro. And transliteration vs more idiomatic: $ diff -w Hyperbolic.translit.java Hyperbolic.fdlibm.java 21c21 < private static double compute(double x) { --- > static double compute(double x) { 26c26 < /* High word of |x|. */ --- > // High word of |x| 28c28 < ix = jx&0x7fffffff; --- > ix = jx & 0x7fff_ffff; 30,31c30,33 < /* x is INF or NaN */ < if(ix>=0x7ff00000) return x+x; --- > // x is INF or NaN > if ( ix >= 0x7ff0_0000) { > return x + x; > } 34,40c36,48 < if (jx<0) h = -h; < /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ < if (ix < 0x40360000) { /* |x|<22 */ < if (ix<0x3e300000) /* |x|<2**-28 */ < if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ < t = FdlibmTranslit.expm1(Math.abs(x)); < if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); --- > if ( jx < 0) { > h = -h; > } > // |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) > if (ix < 0x4036_0000) { // |x| < 22 > if (ix < 0x3e30_0000) // |x| < 2**-28 > if (shuge + x > one) { // sinh(tiny) = tiny with inexact > return x; > } > t = StrictMath.expm1(Math.abs(x)); > if (ix < 0x3ff0_0000) { > return h*(2.0 * t - t*t/(t + one)); > } 44,45c52,55 < /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ < if (ix < 0x40862E42) return h*StrictMath.exp(Math.abs(x)); // TODO switch to translit --- > // |x| in [22, log(maxdouble)] return 0.5*exp(|x|) > if (ix < 0x4086_2E42) { > return h*StrictMath.exp(Math.abs(x)); > } 47,49c57 < /* |x| in [log(maxdouble), overflowthresold] */ < // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); < // lx = (((*(unsigned*)&one)>>29)) + (unsigned*)&x ; --- > // |x| in [log(maxdouble), overflowthresold] 51,52c59,62 < if (ix<0x408633CE || ((ix==0x408633ce)&&(Long.compareUnsigned(lx, 0x8fb9f87d) <= 0 ))) { < w = StrictMath.exp(0.5*Math.abs(x)); // TODO switch to translit --- > if (ix < 0x4086_33CE || > ((ix == 0x4086_33ce) && > (Long.compareUnsigned(lx, 0x8fb9_f87d) <= 0 ))) { > w = StrictMath.exp(0.5 * Math.abs(x)); 57c67 < /* |x| > overflowthresold, sinh(x) overflow */ --- > // |x| > overflowthresold, sinh(x) overflow 84c94 < private static double compute(double x) { --- > static double compute(double x) { 89c99 < /* High word of |x|. */ --- > // High word of |x| 91c101 < ix &= 0x7fffffff; --- > ix &= 0x7fff_ffff; 93,94c103,106 < /* x is INF or NaN */ < if(ix>=0x7ff00000) return x*x; --- > // x is INF or NaN > if (ix >= 0x7ff_00000) { > return x*x; > } 96,98c108,110 < /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ < if(ix<0x3fd62e43) { < t = expm1(Math.abs(x)); --- > // |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) > if (ix < 0x3fd6_2e43) { > t = StrictMath.expm1(Math.abs(x)); 100c112,114 < if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ --- > if (ix < 0x3c80_0000) { // cosh(tiny) = 1 > return w; > } 104,106c118,120 < /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ < if (ix < 0x40360000) { < t = StrictMath.exp(Math.abs(x)); // TODO switch to translit --- > // |x| in [0.5*ln2, 22], return (exp(|x|) + 1/exp(|x|)/2 > if (ix < 0x4036_0000) { > t = StrictMath.exp(Math.abs(x)); 110,111c124,127 < /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ < if (ix < 0x40862E42) return half*StrictMath.exp(Math.abs(x)); // TODO switch to translit --- > // |x| in [22, log(maxdouble)] return half*exp(|x|) > if (ix < 0x4086_2E42) { > return half*StrictMath.exp(Math.abs(x)); > } 113c129 < /* |x| in [log(maxdouble), overflowthresold] */ --- > // |x| in [log(maxdouble), overflowthresold] 115,117c131,134 < if (ix<0x408633CE || < ((ix==0x408633ce)&&(Integer.compareUnsigned(lx, 0x8fb9f87d) <= 0))) { < w = StrictMath.exp(half*Math.abs(x)); // TODO switch to translit --- > if (ix<0x4086_33CE || > ((ix == 0x4086_33ce) && > (Integer.compareUnsigned(lx, 0x8fb9_f87d) <= 0))) { > w = StrictMath.exp(half*Math.abs(x)); 122c139 < /* |x| > overflowthresold, cosh(x) overflow */ --- > // |x| > overflowthresold, cosh(x) overflow 126d142 < 156c172 < /* High word of |x|. */ --- > // High word of |x|. 158c174 < ix = jx&0x7fffffff; --- > ix = jx & 0x7fff_ffff; 160,163c176,182 < /* x is INF or NaN */ < if(ix>=0x7ff00000) { < if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ < else return one/x-one; /* tanh(NaN) = NaN */ --- > // x is INF or NaN > if (ix >= 0x7ff0_0000) { > if (jx >= 0) { // tanh(+-inf)=+-1 > return one/x + one; > } else { // tanh(NaN) = NaN > return one/x - one; > } 166,171c185,190 < /* |x| < 22 */ < if (ix < 0x40360000) { /* |x|<22 */ < if (ix<0x3c800000) /* |x|<2**-55 */ < return x*(one+x); /* tanh(small) = small */ < if (ix>=0x3ff00000) { /* |x|>=1 */ < t = expm1(two*Math.abs(x)); --- > // |x| < 22 > if (ix < 0x4036_0000) { // |x| < 22 > if (ix<0x3c80_0000) // |x| < 2**-55 > return x*(one + x); // tanh(small) = small > if (ix>=0x3ff0_0000) { // |x| >= 1 > t = StrictMath.expm1(two*Math.abs(x)); 174c193 < t = expm1(-two*Math.abs(x)); --- > t = StrictMath.expm1(-two*Math.abs(x)); 177,179c196,197 < /* |x| > 22, return +-1 */ < } else { < z = one - tiny; /* raised inexact flag */ --- > } else { // |x| > 22, return +-1 > z = one - tiny; // raised inexact flag ------------- Commit messages: - JDK-8301444: Port fdlibm hyperbolic transcendental functions to Java Changes: https://git.openjdk.org/jdk/pull/12429/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=12429&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8301444 Stats: 670 lines in 4 files changed: 650 ins; 15 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/12429.diff Fetch: git fetch https://git.openjdk.org/jdk pull/12429/head:pull/12429 PR: https://git.openjdk.org/jdk/pull/12429