> 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
Joe Darcy has updated the pull request incrementally with one additional commit since the last revision: Improve exp usage. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/12429/files - new: https://git.openjdk.org/jdk/pull/12429/files/45d4247f..19fe9857 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=12429&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=12429&range=04-05 Stats: 23 lines in 3 files changed: 6 ins; 4 del; 13 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