diff --git a/configure b/configure index 6c890d0e36b..a9b495bcf09 100755 --- a/configure +++ b/configure @@ -19620,7 +19620,6 @@ for ac_func in \ exp2 \ exp2f \ fmaf \ - lgammaf \ tgamma \ tgammaf diff --git a/configure.ac b/configure.ac index f5bf9bc071f..afb4dc7432a 100644 --- a/configure.ac +++ b/configure.ac @@ -2659,7 +2659,6 @@ AC_CHECK_FUNCS(\ exp2 \ exp2f \ fmaf \ - lgammaf \ tgamma \ tgammaf ) diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 6f0b0c1ba4f..3d8a63a8444 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -636,6 +636,38 @@ static float __expm1f(float x) y = (x - (e + u.f) + 1) * twopk; return y; } + +/* Copied from musl: src/math/__sindf.c */ +static float __sindf(double x) +{ + static const double S1 = -0x15555554cbac77.0p-55, + S2 = 0x111110896efbb2.0p-59, + S3 = -0x1a00f9e2cae774.0p-65, + S4 = 0x16cd878c3b46a7.0p-71; + + double r, s, w, z; + + z = x * x; + w = z * z; + r = S3 + z * S4; + s = z * x; + return (x + s * (S1 + z * S2)) + s * w * r; +} + +/* Copied from musl: src/math/__cosdf.c */ +static float __cosdf(double x) +{ + static const double C0 = -0x1ffffffd0c5e81.0p-54, + C1 = 0x155553e1053a42.0p-57, + C2 = -0x16c087e80f1e27.0p-62, + C3 = 0x199342e0ee5069.0p-68; + double r, w, z; + + z = x * x; + w = z * z; + r = C2 + z * C3; + return ((1.0 + z * C0) + w * C1) + (w * z) * r; +} #endif #ifndef __i386__ @@ -987,38 +1019,6 @@ static int __rem_pio2f(float x, double *y) return n; } -/* Copied from musl: src/math/__sindf.c */ -static float __sindf(double x) -{ - static const double S1 = -0x15555554cbac77.0p-55, - S2 = 0x111110896efbb2.0p-59, - S3 = -0x1a00f9e2cae774.0p-65, - S4 = 0x16cd878c3b46a7.0p-71; - - double r, s, w, z; - - z = x * x; - w = z * z; - r = S3 + z * S4; - s = z * x; - return (x + s * (S1 + z * S2)) + s * w * r; -} - -/* Copied from musl: src/math/__cosdf.c */ -static float __cosdf(double x) -{ - static const double C0 = -0x1ffffffd0c5e81.0p-54, - C1 = 0x155553e1053a42.0p-57, - C2 = -0x16c087e80f1e27.0p-62, - C3 = 0x199342e0ee5069.0p-68; - double r, w, z; - - z = x * x; - w = z * z; - r = C2 + z * C3; - return ((1.0 + z * C0) + w * C1) + (w * z) * r; -} - /********************************************************************* * cosf (MSVCRT.@) * @@ -8846,12 +8846,205 @@ double CDECL lgamma(double x) return r; } +/* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */ +static float sinf_pi(float x) +{ + double y; + int n; + + /* spurious inexact if odd int */ + x = 2 * (x * 0.5f - floorf(x * 0.5f)); /* x mod 2.0 */ + + n = (int)(x * 4); + n = (n + 1) / 2; + y = x - n * 0.5f; + y *= M_PI; + switch (n) { + default: /* case 4: */ + case 0: return __sindf(y); + case 1: return __cosdf(y); + case 2: return __sindf(-y); + case 3: return -__cosdf(y); + } +} + /********************************************************************* * lgammaf (MSVCR120.@) + * + * Copied from musl: src/math/lgammaf_r.c */ float CDECL lgammaf(float x) { - return unix_funcs->lgammaf( x ); + static const float pi = 3.1415927410e+00, + a0 = 7.7215664089e-02, + a1 = 3.2246702909e-01, + a2 = 6.7352302372e-02, + a3 = 2.0580807701e-02, + a4 = 7.3855509982e-03, + a5 = 2.8905137442e-03, + a6 = 1.1927076848e-03, + a7 = 5.1006977446e-04, + a8 = 2.2086278477e-04, + a9 = 1.0801156895e-04, + a10 = 2.5214456400e-05, + a11 = 4.4864096708e-05, + tc = 1.4616321325e+00, + tf = -1.2148628384e-01, + tt = 6.6971006518e-09, + t0 = 4.8383611441e-01, + t1 = -1.4758771658e-01, + t2 = 6.4624942839e-02, + t3 = -3.2788541168e-02, + t4 = 1.7970675603e-02, + t5 = -1.0314224288e-02, + t6 = 6.1005386524e-03, + t7 = -3.6845202558e-03, + t8 = 2.2596477065e-03, + t9 = -1.4034647029e-03, + t10 = 8.8108185446e-04, + t11 = -5.3859531181e-04, + t12 = 3.1563205994e-04, + t13 = -3.1275415677e-04, + t14 = 3.3552918467e-04, + u0 = -7.7215664089e-02, + u1 = 6.3282704353e-01, + u2 = 1.4549225569e+00, + u3 = 9.7771751881e-01, + u4 = 2.2896373272e-01, + u5 = 1.3381091878e-02, + v1 = 2.4559779167e+00, + v2 = 2.1284897327e+00, + v3 = 7.6928514242e-01, + v4 = 1.0422264785e-01, + v5 = 3.2170924824e-03, + s0 = -7.7215664089e-02, + s1 = 2.1498242021e-01, + s2 = 3.2577878237e-01, + s3 = 1.4635047317e-01, + s4 = 2.6642270386e-02, + s5 = 1.8402845599e-03, + s6 = 3.1947532989e-05, + r1 = 1.3920053244e+00, + r2 = 7.2193557024e-01, + r3 = 1.7193385959e-01, + r4 = 1.8645919859e-02, + r5 = 7.7794247773e-04, + r6 = 7.3266842264e-06, + w0 = 4.1893854737e-01, + w1 = 8.3333335817e-02, + w2 = -2.7777778450e-03, + w3 = 7.9365057172e-04, + w4 = -5.9518753551e-04, + w5 = 8.3633989561e-04, + w6 = -1.6309292987e-03; + + union {float f; UINT32 i;} u = {x}; + float t, y, z, nadj, p, p1, p2, p3, q, r, w; + UINT32 ix; + int i, sign; + + /* purge off +-inf, NaN, +-0, tiny and negative arguments */ + sign = u.i >> 31; + ix = u.i & 0x7fffffff; + if (ix >= 0x7f800000) + return x * x; + if (ix < 0x35000000) { /* |x| < 2**-21, return -log(|x|) */ + if (sign) + x = -x; + return -logf(x); + } + if (sign) { + x = -x; + t = sinf_pi(x); + if (t == 0.0f) { /* -integer */ + *_errno() = ERANGE; + return 1.0f / (x - x); + } + if (t <= 0.0f) + t = -t; + nadj = logf(pi / (t * x)); + } + + /* purge off 1 and 2 */ + if (ix == 0x3f800000 || ix == 0x40000000) + r = 0; + /* for x < 2.0 */ + else if (ix < 0x40000000) { + if (ix <= 0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */ + r = -logf(x); + if (ix >= 0x3f3b4a20) { + y = 1.0f - x; + i = 0; + } else if (ix >= 0x3e6d3308) { + y = x - (tc - 1.0f); + i = 1; + } else { + y = x; + i = 2; + } + } else { + r = 0.0f; + if (ix >= 0x3fdda618) { /* [1.7316,2] */ + y = 2.0f - x; + i = 0; + } else if (ix >= 0x3F9da620) { /* [1.23,1.73] */ + y = x - tc; + i = 1; + } else { + y = x - 1.0f; + i = 2; + } + } + switch(i) { + case 0: + z = y * y; + p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10)))); + p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11))))); + p = y * p1 + p2; + r += p - 0.5f * y; + break; + case 1: + z = y * y; + w = z * y; + p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12))); /* parallel comp */ + p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13))); + p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14))); + p = z * p1 - (tt - w * (p2 + y * p3)); + r += (tf + p); + break; + case 2: + p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5))))); + p2 = 1.0f + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5)))); + r += -0.5f * y + p1 / p2; + } + } else if (ix < 0x41000000) { /* x < 8.0 */ + i = (int)x; + y = x - (float)i; + p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6)))))); + q = 1.0f + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6))))); + r = 0.5f * y + p / q; + z = 1.0f; /* lgamma(1+s) = log(s) + lgamma(s) */ + switch (i) { + case 7: z *= y + 6.0f; /* fall through */ + case 6: z *= y + 5.0f; /* fall through */ + case 5: z *= y + 4.0f; /* fall through */ + case 4: z *= y + 3.0f; /* fall through */ + case 3: + z *= y + 2.0f; + r += logf(z); + break; + } + } else if (ix < 0x5c800000) { /* 8.0 <= x < 2**58 */ + t = logf(x); + z = 1.0f / x; + y = z * z; + w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6))))); + r = (x - 0.5f) * (t - 1.0f) + w; + } else /* 2**58 <= x <= inf */ + r = x * (logf(x) - 1.0f); + if (sign) + r = nadj - r; + return r; } /********************************************************************* diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 14aeef4c1e7..012ec6f6b85 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -94,19 +94,6 @@ static float CDECL unix_fmaf( float x, float y, float z ) #endif } -/********************************************************************* - * lgammaf - */ -static float CDECL unix_lgammaf(float x) -{ -#ifdef HAVE_LGAMMAF - return lgammaf(x); -#else - FIXME( "not implemented\n" ); - return 0; -#endif -} - /********************************************************************* * pow */ @@ -156,7 +143,6 @@ static const struct unix_funcs funcs = unix_exp2, unix_exp2f, unix_fmaf, - unix_lgammaf, unix_pow, unix_powf, unix_tgamma, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 4309ff835a0..a9c569d6f63 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -28,7 +28,6 @@ struct unix_funcs double (CDECL *exp2)(double x); float (CDECL *exp2f)(float x); float (CDECL *fmaf)(float x, float y, float z); - float (CDECL *lgammaf)(float x); double (CDECL *pow)(double x, double y); float (CDECL *powf)(float x, float y); double (CDECL *tgamma)(double x); diff --git a/include/config.h.in b/include/config.h.in index dd34230b268..537dda5f68d 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -297,9 +297,6 @@ /* Define to 1 if you have the `ldap_parse_vlv_control' function. */ #undef HAVE_LDAP_PARSE_VLV_CONTROL -/* Define to 1 if you have the `lgammaf' function. */ -#undef HAVE_LGAMMAF - /* Define to 1 if you have the `gettextpo' library (-lgettextpo). */ #undef HAVE_LIBGETTEXTPO