diff --git a/lib/msun/bsdsrc/b_exp.c b/lib/msun/bsdsrc/b_exp.c index 398755a0aaeb..44cd5190de92 100644 --- a/lib/msun/bsdsrc/b_exp.c +++ b/lib/msun/bsdsrc/b_exp.c @@ -1,124 +1,122 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* @(#)exp.c 8.1 (Berkeley) 6/4/93 */ -#include /* EXP(X) * RETURN THE EXPONENTIAL OF X * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS) * CODED IN C BY K.C. NG, 1/19/85; * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86. * * Required system supported functions: * ldexp(x,n) * copysign(x,y) * isfinite(x) * * Method: * 1. Argument Reduction: given the input x, find r and integer k such * that * x = k*ln2 + r, |r| <= 0.5*ln2. * r will be represented as r := z+c for better accuracy. * * 2. Compute exp(r) by * * exp(r) = 1 + r + r*R1/(2-R1), * where * R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))). * * 3. exp(x) = 2^k * exp(r) . * * Special cases: * exp(INF) is INF, exp(NaN) is NaN; * exp(-INF)= 0; * for finite argument, only exp(0)=1 is exact. * * Accuracy: * exp(x) returns the exponential of x nearly rounded. In a test run * with 1,156,000 random arguments on a VAX, the maximum observed * error was 0.869 ulps (units in the last place). */ static const double p1 = 1.6666666666666660e-01, /* 0x3fc55555, 0x55555553 */ p2 = -2.7777777777564776e-03, /* 0xbf66c16c, 0x16c0ac3c */ p3 = 6.6137564717940088e-05, /* 0x3f11566a, 0xb5c2ba0d */ p4 = -1.6534060280704225e-06, /* 0xbebbbd53, 0x273e8fb7 */ p5 = 4.1437773411069054e-08; /* 0x3e663f2a, 0x09c94b6c */ static const double ln2hi = 0x1.62e42fee00000p-1, /* High 32 bits round-down. */ ln2lo = 0x1.a39ef35793c76p-33; /* Next 53 bits round-to-nearst. */ static const double lnhuge = 0x1.6602b15b7ecf2p9, /* (DBL_MAX_EXP + 9) * log(2.) */ lntiny = -0x1.77af8ebeae354p9, /* (DBL_MIN_EXP - 53 - 10) * log(2.) */ invln2 = 0x1.71547652b82fep0; /* 1 / log(2.) */ /* returns exp(r = x + c) for |c| < |x| with no overlap. */ static double __exp__D(double x, double c) { double hi, lo, z; int k; if (x != x) /* x is NaN. */ return(x); if (x <= lnhuge) { if (x >= lntiny) { /* argument reduction: x --> x - k*ln2 */ z = invln2 * x; k = z + copysign(0.5, x); /* * Express (x + c) - k * ln2 as hi - lo. * Let x = hi - lo rounded. */ hi = x - k * ln2hi; /* Exact. */ lo = k * ln2lo - c; x = hi - lo; /* Return 2^k*[1+x+x*c/(2+c)] */ z = x * x; c = x - z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5)))); c = (x * c) / (2 - c); return (ldexp(1 + (hi - (lo - c)), k)); } else { /* exp(-INF) is 0. exp(-big) underflows to 0. */ return (isfinite(x) ? ldexp(1., -5000) : 0); } } else /* exp(INF) is INF, exp(+big#) overflows to INF */ return (isfinite(x) ? ldexp(1., 5000) : x); } diff --git a/lib/msun/bsdsrc/b_log.c b/lib/msun/bsdsrc/b_log.c index aeec29368412..a82140bb98b5 100644 --- a/lib/msun/bsdsrc/b_log.c +++ b/lib/msun/bsdsrc/b_log.c @@ -1,402 +1,400 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* @(#)log.c 8.2 (Berkeley) 11/30/93 */ -#include /* Table-driven natural logarithm. * * This code was derived, with minor modifications, from: * Peter Tang, "Table-Driven Implementation of the * Logarithm in IEEE Floating-Point arithmetic." ACM Trans. * Math Software, vol 16. no 4, pp 378-400, Dec 1990). * * Calculates log(2^m*F*(1+f/F)), |f/F| <= 1/256, * where F = j/128 for j an integer in [0, 128]. * * log(2^m) = log2_hi*m + log2_tail*m * The leading term is exact, because m is an integer, * m has at most 10 digits (for subnormal numbers), * and log2_hi has 11 trailing zero bits. * * log(F) = logF_hi[j] + logF_lo[j] is in table below. * logF_hi[] + 512 is exact. * * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ... * * The leading term is calculated to extra precision in two * parts, the larger of which adds exactly to the dominant * m and F terms. * * There are two cases: * 1. When m and j are non-zero (m | j), use absolute * precision for the leading term. * 2. When m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1). * In this case, use a relative precision of 24 bits. * (This is done differently in the original paper) * * Special cases: * 0 return signalling -Inf * neg return signalling NaN * +Inf return +Inf */ #define N 128 /* * Coefficients in the polynomial approximation of log(1+f/F). * Domain of x is [0,1./256] with 2**(-64.187) precision. */ static const double A1 = 8.3333333333333329e-02, /* 0x3fb55555, 0x55555555 */ A2 = 1.2499999999943598e-02, /* 0x3f899999, 0x99991a98 */ A3 = 2.2321527525957776e-03; /* 0x3f624929, 0xe24e70be */ /* * Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128. * Used for generation of extend precision logarithms. * The constant 35184372088832 is 2^45, so the divide is exact. * It ensures correct reading of logF_head, even for inaccurate * decimal-to-binary conversion routines. (Everybody gets the * right answer for integers less than 2^53.) * Values for log(F) were generated using error < 10^-57 absolute * with the bc -l package. */ static double logF_head[N+1] = { 0., .007782140442060381246, .015504186535963526694, .023167059281547608406, .030771658666765233647, .038318864302141264488, .045809536031242714670, .053244514518837604555, .060624621816486978786, .067950661908525944454, .075223421237524235039, .082443669210988446138, .089612158689760690322, .096729626458454731618, .103796793681567578460, .110814366340264314203, .117783035656430001836, .124703478501032805070, .131576357788617315236, .138402322859292326029, .145182009844575077295, .151916042025732167530, .158605030176659056451, .165249572895390883786, .171850256926518341060, .178407657472689606947, .184922338493834104156, .191394852999565046047, .197825743329758552135, .204215541428766300668, .210564769107350002741, .216873938300523150246, .223143551314024080056, .229374101064877322642, .235566071312860003672, .241719936886966024758, .247836163904594286577, .253915209980732470285, .259957524436686071567, .265963548496984003577, .271933715484010463114, .277868451003087102435, .283768173130738432519, .289633292582948342896, .295464212893421063199, .301261330578199704177, .307025035294827830512, .312755710004239517729, .318453731118097493890, .324119468654316733591, .329753286372579168528, .335355541920762334484, .340926586970454081892, .346466767346100823488, .351976423156884266063, .357455888922231679316, .362905493689140712376, .368325561158599157352, .373716409793814818840, .379078352934811846353, .384411698910298582632, .389716751140440464951, .394993808240542421117, .400243164127459749579, .405465108107819105498, .410659924985338875558, .415827895143593195825, .420969294644237379543, .426084395310681429691, .431173464818130014464, .436236766774527495726, .441274560805140936281, .446287102628048160113, .451274644139630254358, .456237433481874177232, .461175715122408291790, .466089729924533457960, .470979715219073113985, .475845904869856894947, .480688529345570714212, .485507815781602403149, .490303988045525329653, .495077266798034543171, .499827869556611403822, .504556010751912253908, .509261901790523552335, .513945751101346104405, .518607764208354637958, .523248143765158602036, .527867089620485785417, .532464798869114019908, .537041465897345915436, .541597282432121573947, .546132437597407260909, .550647117952394182793, .555141507540611200965, .559615787935399566777, .564070138285387656651, .568504735352689749561, .572919753562018740922, .577315365035246941260, .581691739635061821900, .586049045003164792433, .590387446602107957005, .594707107746216934174, .599008189645246602594, .603290851438941899687, .607555250224322662688, .611801541106615331955, .616029877215623855590, .620240409751204424537, .624433288012369303032, .628608659422752680256, .632766669570628437213, .636907462236194987781, .641031179420679109171, .645137961373620782978, .649227946625615004450, .653301272011958644725, .657358072709030238911, .661398482245203922502, .665422632544505177065, .669430653942981734871, .673422675212350441142, .677398823590920073911, .681359224807238206267, .685304003098281100392, .689233281238557538017, .693147180560117703862 }; static double logF_tail[N+1] = { 0., -.00000000000000543229938420049, .00000000000000172745674997061, -.00000000000001323017818229233, -.00000000000001154527628289872, -.00000000000000466529469958300, .00000000000005148849572685810, -.00000000000002532168943117445, -.00000000000005213620639136504, -.00000000000001819506003016881, .00000000000006329065958724544, .00000000000008614512936087814, -.00000000000007355770219435028, .00000000000009638067658552277, .00000000000007598636597194141, .00000000000002579999128306990, -.00000000000004654729747598444, -.00000000000007556920687451336, .00000000000010195735223708472, -.00000000000017319034406422306, -.00000000000007718001336828098, .00000000000010980754099855238, -.00000000000002047235780046195, -.00000000000008372091099235912, .00000000000014088127937111135, .00000000000012869017157588257, .00000000000017788850778198106, .00000000000006440856150696891, .00000000000016132822667240822, -.00000000000007540916511956188, -.00000000000000036507188831790, .00000000000009120937249914984, .00000000000018567570959796010, -.00000000000003149265065191483, -.00000000000009309459495196889, .00000000000017914338601329117, -.00000000000001302979717330866, .00000000000023097385217586939, .00000000000023999540484211737, .00000000000015393776174455408, -.00000000000036870428315837678, .00000000000036920375082080089, -.00000000000009383417223663699, .00000000000009433398189512690, .00000000000041481318704258568, -.00000000000003792316480209314, .00000000000008403156304792424, -.00000000000034262934348285429, .00000000000043712191957429145, -.00000000000010475750058776541, -.00000000000011118671389559323, .00000000000037549577257259853, .00000000000013912841212197565, .00000000000010775743037572640, .00000000000029391859187648000, -.00000000000042790509060060774, .00000000000022774076114039555, .00000000000010849569622967912, -.00000000000023073801945705758, .00000000000015761203773969435, .00000000000003345710269544082, -.00000000000041525158063436123, .00000000000032655698896907146, -.00000000000044704265010452446, .00000000000034527647952039772, -.00000000000007048962392109746, .00000000000011776978751369214, -.00000000000010774341461609578, .00000000000021863343293215910, .00000000000024132639491333131, .00000000000039057462209830700, -.00000000000026570679203560751, .00000000000037135141919592021, -.00000000000017166921336082431, -.00000000000028658285157914353, -.00000000000023812542263446809, .00000000000006576659768580062, -.00000000000028210143846181267, .00000000000010701931762114254, .00000000000018119346366441110, .00000000000009840465278232627, -.00000000000033149150282752542, -.00000000000018302857356041668, -.00000000000016207400156744949, .00000000000048303314949553201, -.00000000000071560553172382115, .00000000000088821239518571855, -.00000000000030900580513238244, -.00000000000061076551972851496, .00000000000035659969663347830, .00000000000035782396591276383, -.00000000000046226087001544578, .00000000000062279762917225156, .00000000000072838947272065741, .00000000000026809646615211673, -.00000000000010960825046059278, .00000000000002311949383800537, -.00000000000058469058005299247, -.00000000000002103748251144494, -.00000000000023323182945587408, -.00000000000042333694288141916, -.00000000000043933937969737844, .00000000000041341647073835565, .00000000000006841763641591466, .00000000000047585534004430641, .00000000000083679678674757695, -.00000000000085763734646658640, .00000000000021913281229340092, -.00000000000062242842536431148, -.00000000000010983594325438430, .00000000000065310431377633651, -.00000000000047580199021710769, -.00000000000037854251265457040, .00000000000040939233218678664, .00000000000087424383914858291, .00000000000025218188456842882, -.00000000000003608131360422557, -.00000000000050518555924280902, .00000000000078699403323355317, -.00000000000067020876961949060, .00000000000016108575753932458, .00000000000058527188436251509, -.00000000000035246757297904791, -.00000000000018372084495629058, .00000000000088606689813494916, .00000000000066486268071468700, .00000000000063831615170646519, .00000000000025144230728376072, -.00000000000017239444525614834 }; /* * Extra precision variant, returning struct {double a, b;}; * log(x) = a+b to 63 bits, with 'a' rounded to 24 bits. */ static struct Double __log__D(double x) { int m, j; double F, f, g, q, u, v, u1, u2; struct Double r; /* * Argument reduction: 1 <= g < 2; x/2^m = g; * y = F*(1 + f/F) for |f| <= 2^-8 */ g = frexp(x, &m); g *= 2; m--; if (m == -1022) { j = ilogb(g); m += j; g = ldexp(g, -j); } j = N * (g - 1) + 0.5; F = (1. / N) * j + 1; f = g - F; g = 1 / (2 * F + f); u = 2 * f * g; v = u * u; q = u * v * (A1 + v * (A2 + v * A3)); if (m | j) { u1 = u + 513; u1 -= 513; } else { u1 = (float)u; } u2 = (2 * (f - F * u1) - u1 * f) * g; u1 += m * logF_head[N] + logF_head[j]; u2 += logF_tail[j]; u2 += q; u2 += logF_tail[N] * m; r.a = (float)(u1 + u2); /* Only difference is here. */ r.b = (u1 - r.a) + u2; return (r); } diff --git a/lib/msun/bsdsrc/b_tgamma.c b/lib/msun/bsdsrc/b_tgamma.c index cc9f8f70297e..8369477c18b7 100644 --- a/lib/msun/bsdsrc/b_tgamma.c +++ b/lib/msun/bsdsrc/b_tgamma.c @@ -1,398 +1,396 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * The original code, FreeBSD's old svn r93211, contained the following * attribution: * * This code by P. McIlroy, Oct 1992; * * The financial support of UUNET Communications Services is greatfully * acknowledged. * * The algorithm remains, but the code has been re-arranged to facilitate * porting to other precisions. */ -/* @(#)gamma.c 8.1 (Berkeley) 6/4/93 */ -#include #include #include "math.h" #include "math_private.h" /* Used in b_log.c and below. */ struct Double { double a; double b; }; #include "b_log.c" #include "b_exp.c" /* * The range is broken into several subranges. Each is handled by its * helper functions. * * x >= 6.0: large_gam(x) * 6.0 > x >= xleft: small_gam(x) where xleft = 1 + left + x0. * xleft > x > iota: smaller_gam(x) where iota = 1e-17. * iota > x > -itoa: Handle x near 0. * -iota > x : neg_gam * * Special values: * -Inf: return NaN and raise invalid; * negative integer: return NaN and raise invalid; * other x ~< 177.79: return +-0 and raise underflow; * +-0: return +-Inf and raise divide-by-zero; * finite x ~> 171.63: return +Inf and raise overflow; * +Inf: return +Inf; * NaN: return NaN. * * Accuracy: tgamma(x) is accurate to within * x > 0: error provably < 0.9ulp. * Maximum observed in 1,000,000 trials was .87ulp. * x < 0: * Maximum observed error < 4ulp in 1,000,000 trials. */ /* * Constants for large x approximation (x in [6, Inf]) * (Accurate to 2.8*10^-19 absolute) */ static const double zero = 0.; static const volatile double tiny = 1e-300; /* * x >= 6 * * Use the asymptotic approximation (Stirling's formula) adjusted fof * equal-ripples: * * log(G(x)) ~= (x-0.5)*(log(x)-1) + 0.5(log(2*pi)-1) + 1/x*P(1/(x*x)) * * Keep extra precision in multiplying (x-.5)(log(x)-1), to avoid * premature round-off. * * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error. */ static const double ln2pi_hi = 0.41894531250000000, ln2pi_lo = -6.7792953272582197e-6, Pa0 = 8.3333333333333329e-02, /* 0x3fb55555, 0x55555555 */ Pa1 = -2.7777777777735404e-03, /* 0xbf66c16c, 0x16c145ec */ Pa2 = 7.9365079044114095e-04, /* 0x3f4a01a0, 0x183de82d */ Pa3 = -5.9523715464225254e-04, /* 0xbf438136, 0x0e681f62 */ Pa4 = 8.4161391899445698e-04, /* 0x3f4b93f8, 0x21042a13 */ Pa5 = -1.9065246069191080e-03, /* 0xbf5f3c8b, 0x357cb64e */ Pa6 = 5.9047708485785158e-03, /* 0x3f782f99, 0xdaf5d65f */ Pa7 = -1.6484018705183290e-02; /* 0xbf90e12f, 0xc4fb4df0 */ static struct Double large_gam(double x) { double p, z, thi, tlo, xhi, xlo; struct Double u; z = 1 / (x * x); p = Pa0 + z * (Pa1 + z * (Pa2 + z * (Pa3 + z * (Pa4 + z * (Pa5 + z * (Pa6 + z * Pa7)))))); p = p / x; u = __log__D(x); u.a -= 1; /* Split (x - 0.5) in high and low parts. */ x -= 0.5; xhi = (float)x; xlo = x - xhi; /* Compute t = (x-.5)*(log(x)-1) in extra precision. */ thi = xhi * u.a; tlo = xlo * u.a + x * u.b; /* Compute thi + tlo + ln2pi_hi + ln2pi_lo + p. */ tlo += ln2pi_lo; tlo += p; u.a = ln2pi_hi + tlo; u.a += thi; u.b = thi - u.a; u.b += ln2pi_hi; u.b += tlo; return (u); } /* * Rational approximation, A0 + x * x * P(x) / Q(x), on the interval * [1.066.., 2.066..] accurate to 4.25e-19. * * Returns r.a + r.b = a0 + (z + c)^2 * p / q, with r.a truncated. */ static const double #if 0 a0_hi = 8.8560319441088875e-1, a0_lo = -4.9964270364690197e-17, #else a0_hi = 8.8560319441088875e-01, /* 0x3fec56dc, 0x82a74aef */ a0_lo = -4.9642368725563397e-17, /* 0xbc8c9deb, 0xaa64afc3 */ #endif P0 = 6.2138957182182086e-1, P1 = 2.6575719865153347e-1, P2 = 5.5385944642991746e-3, P3 = 1.3845669830409657e-3, P4 = 2.4065995003271137e-3, Q0 = 1.4501953125000000e+0, Q1 = 1.0625852194801617e+0, Q2 = -2.0747456194385994e-1, Q3 = -1.4673413178200542e-1, Q4 = 3.0787817615617552e-2, Q5 = 5.1244934798066622e-3, Q6 = -1.7601274143166700e-3, Q7 = 9.3502102357378894e-5, Q8 = 6.1327550747244396e-6; static struct Double ratfun_gam(double z, double c) { double p, q, thi, tlo; struct Double r; q = Q0 + z * (Q1 + z * (Q2 + z * (Q3 + z * (Q4 + z * (Q5 + z * (Q6 + z * (Q7 + z * Q8))))))); p = P0 + z * (P1 + z * (P2 + z * (P3 + z * P4))); p = p / q; /* Split z into high and low parts. */ thi = (float)z; tlo = (z - thi) + c; tlo *= (thi + z); /* Split (z+c)^2 into high and low parts. */ thi *= thi; q = thi; thi = (float)thi; tlo += (q - thi); /* Split p/q into high and low parts. */ r.a = (float)p; r.b = p - r.a; tlo = tlo * p + thi * r.b + a0_lo; thi *= r.a; /* t = (z+c)^2*(P/Q) */ r.a = (float)(thi + a0_hi); r.b = ((a0_hi - r.a) + thi) + tlo; return (r); /* r = a0 + t */ } /* * x < 6 * * Use argument reduction G(x+1) = xG(x) to reach the range [1.066124, * 2.066124]. Use a rational approximation centered at the minimum * (x0+1) to ensure monotonicity. * * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.) * It also has correct monotonicity. */ static const double left = -0.3955078125, /* left boundary for rat. approx */ x0 = 4.6163214496836236e-1; /* xmin - 1 */ static double small_gam(double x) { double t, y, ym1; struct Double yy, r; y = x - 1; if (y <= 1 + (left + x0)) { yy = ratfun_gam(y - x0, 0); return (yy.a + yy.b); } r.a = (float)y; yy.a = r.a - 1; y = y - 1 ; r.b = yy.b = y - yy.a; /* Argument reduction: G(x+1) = x*G(x) */ for (ym1 = y - 1; ym1 > left + x0; y = ym1--, yy.a--) { t = r.a * yy.a; r.b = r.a * yy.b + y * r.b; r.a = (float)t; r.b += (t - r.a); } /* Return r*tgamma(y). */ yy = ratfun_gam(y - x0, 0); y = r.b * (yy.a + yy.b) + r.a * yy.b; y += yy.a * r.a; return (y); } /* * Good on (0, 1+x0+left]. Accurate to 1 ulp. */ static double smaller_gam(double x) { double d, rhi, rlo, t, xhi, xlo; struct Double r; if (x < x0 + left) { t = (float)x; d = (t + x) * (x - t); t *= t; xhi = (float)(t + x); xlo = x - xhi; xlo += t; xlo += d; t = 1 - x0; t += x; d = 1 - x0; d -= t; d += x; x = xhi + xlo; } else { xhi = (float)x; xlo = x - xhi; t = x - x0; d = - x0 - t; d += x; } r = ratfun_gam(t, d); d = (float)(r.a / x); r.a -= d * xhi; r.a -= d * xlo; r.a += r.b; return (d + r.a / x); } /* * x < 0 * * Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x)). * At negative integers, return NaN and raise invalid. */ static double neg_gam(double x) { int sgn = 1; struct Double lg, lsine; double y, z; y = ceil(x); if (y == x) /* Negative integer. */ return ((x - x) / zero); z = y - x; if (z > 0.5) z = 1 - z; y = y / 2; if (y == ceil(y)) sgn = -1; if (z < 0.25) z = sinpi(z); else z = cospi(0.5 - z); /* Special case: G(1-x) = Inf; G(x) may be nonzero. */ if (x < -170) { if (x < -190) return (sgn * tiny * tiny); y = 1 - x; /* exact: 128 < |x| < 255 */ lg = large_gam(y); lsine = __log__D(M_PI / z); /* = TRUNC(log(u)) + small */ lg.a -= lsine.a; /* exact (opposite signs) */ lg.b -= lsine.b; y = -(lg.a + lg.b); z = (y + lg.a) + lg.b; y = __exp__D(y, z); if (sgn < 0) y = -y; return (y); } y = 1 - x; if (1 - y == x) y = tgamma(y); else /* 1-x is inexact */ y = - x * tgamma(-x); if (sgn < 0) y = -y; return (M_PI / (y * z)); } /* * xmax comes from lgamma(xmax) - emax * log(2) = 0. * static const float xmax = 35.040095f * static const double xmax = 171.624376956302725; * ld80: LD80C(0xdb718c066b352e20, 10, 1.75554834290446291689e+03L), * ld128: 1.75554834290446291700388921607020320e+03L, * * iota is a sloppy threshold to isolate x = 0. */ static const double xmax = 171.624376956302725; static const double iota = 0x1p-56; double tgamma(double x) { struct Double u; if (x >= 6) { if (x > xmax) return (x / zero); u = large_gam(x); return (__exp__D(u.a, u.b)); } if (x >= 1 + left + x0) return (small_gam(x)); if (x > iota) return (smaller_gam(x)); if (x > -iota) { if (x != 0.) u.a = 1 - tiny; /* raise inexact */ return (1 / x); } if (!isfinite(x)) return (x - x); /* x is NaN or -Inf */ return (neg_gam(x)); } #if (LDBL_MANT_DIG == 53) __weak_reference(tgamma, tgammal); #endif diff --git a/lib/msun/bsdsrc/mathimpl.h b/lib/msun/bsdsrc/mathimpl.h index 3d6554747dac..a7d2c59476b5 100644 --- a/lib/msun/bsdsrc/mathimpl.h +++ b/lib/msun/bsdsrc/mathimpl.h @@ -1,75 +1,74 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mathimpl.h 8.1 (Berkeley) 6/4/93 */ #ifndef _MATHIMPL_H_ #define _MATHIMPL_H_ -#include #include #include "../src/math_private.h" /* * TRUNC() is a macro that sets the trailing 27 bits in the mantissa of an * IEEE double variable to zero. It must be expression-like for syntactic * reasons, and we implement this expression using an inline function * instead of a pure macro to avoid depending on the gcc feature of * statement-expressions. */ #define TRUNC(d) (_b_trunc(&(d))) static __inline void _b_trunc(volatile double *_dp) { uint32_t _lw; GET_LOW_WORD(_lw, *_dp); SET_LOW_WORD(*_dp, _lw & 0xf8000000); } struct Double { double a; double b; }; /* * Functions internal to the math package, yet not static. */ double __exp__D(double, double); struct Double __log__D(double); #endif /* !_MATHIMPL_H_ */ diff --git a/lib/msun/i387/invtrig.c b/lib/msun/i387/invtrig.c index 523f022e0546..50d8d3af9343 100644 --- a/lib/msun/i387/invtrig.c +++ b/lib/msun/i387/invtrig.c @@ -1,86 +1,85 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #define STRUCT_DECLS #include "invtrig.h" /* * asinl() and acosl() */ const LONGDOUBLE pS0 = { 0xaaaaaaaaaaaaaaa8ULL, 0x3ffcU }, /* 1.66666666666666666631e-01L */ pS1 = { 0xd5271b6699b48bfaULL, 0xbffdU }, /* -4.16313987993683104320e-01L */ pS2 = { 0xbcf67ca9e9f669cfULL, 0x3ffdU }, /* 3.69068046323246813704e-01L */ pS3 = { 0x8b7baa3d15f9830dULL, 0xbffcU }, /* -1.36213932016738603108e-01L */ pS4 = { 0x92154b093a3bff1cULL, 0x3ff9U }, /* 1.78324189708471965733e-02L */ pS5 = { 0xe5dd76401964508cULL, 0xbff2U }, /* -2.19216428382605211588e-04L */ pS6 = { 0xee69c5b0fdb76951ULL, 0xbfedU }, /* -7.10526623669075243183e-06L */ qS1 = { 0xbcaa2159c01436a0ULL, 0xc000U }, /* -2.94788392796209867269e+00L */ qS2 = { 0xd17a73d1e1564c29ULL, 0x4000U }, /* 3.27309890266528636716e+00L */ qS3 = { 0xd767e411c9cf4c2cULL, 0xbfffU }, /* -1.68285799854822427013e+00L */ qS4 = { 0xc809c0dfb9b0d0b7ULL, 0x3ffdU }, /* 3.90699412641738801874e-01L */ qS5 = { 0x80c3a2197c8ced57ULL, 0xbffaU }; /* -3.14365703596053263322e-02L */ /* * atanl() */ const LONGDOUBLE atanhi[] = { { 0xed63382b0dda7b45ULL, 0x3ffdU }, /* 4.63647609000806116202e-01L */ { 0xc90fdaa22168c235ULL, 0x3ffeU }, /* 7.85398163397448309628e-01L */ { 0xfb985e940fb4d900ULL, 0x3ffeU }, /* 9.82793723247329067960e-01L */ { 0xc90fdaa22168c235ULL, 0x3fffU }, /* 1.57079632679489661926e+00L */ }; const LONGDOUBLE atanlo[] = { { 0xdfc88bd978751a07ULL, 0x3fbcU }, /* 1.18469937025062860669e-20L */ { 0xece675d1fc8f8cbbULL, 0xbfbcU }, /* -1.25413940316708300586e-20L */ { 0xf10f5e197793c283ULL, 0x3fbdU }, /* 2.55232234165405176172e-20L */ { 0xece675d1fc8f8cbbULL, 0xbfbdU }, /* -2.50827880633416601173e-20L */ }; const LONGDOUBLE aT[] = { { 0xaaaaaaaaaaaaaa9fULL, 0x3ffdU }, /* 3.33333333333333333017e-01L */ { 0xcccccccccccc62bcULL, 0xbffcU }, /* -1.99999999999999632011e-01L */ { 0x9249249248b81e3fULL, 0x3ffcU }, /* 1.42857142857046531280e-01L */ { 0xe38e38e3316f3de5ULL, 0xbffbU }, /* -1.11111111100562372733e-01L */ { 0xba2e8b8dc280726aULL, 0x3ffbU }, /* 9.09090902935647302252e-02L */ { 0x9d89d5b4c6847ec4ULL, 0xbffbU }, /* -7.69230552476207730353e-02L */ { 0x8888461d3099c677ULL, 0x3ffbU }, /* 6.66661718042406260546e-02L */ { 0xf0e8ee0f5328dc29ULL, 0xbffaU }, /* -5.88158892835030888692e-02L */ { 0xd73ea84d24bae54aULL, 0x3ffaU }, /* 5.25499891539726639379e-02L */ { 0xc08fa381dcd9213aULL, 0xbffaU }, /* -4.70119845393155721494e-02L */ { 0xa54a26f4095f2a3aULL, 0x3ffaU }, /* 4.03539201366454414072e-02L */ { 0xeea2d8d059ef3ad6ULL, 0xbff9U }, /* -2.91303858419364158725e-02L */ { 0xcc82292ab894b051ULL, 0x3ff8U }, /* 1.24822046299269234080e-02L */ }; const LONGDOUBLE pi_lo = { 0xece675d1fc8f8cbbULL, 0xbfbeU }; /* -5.01655761266833202345e-20L */ diff --git a/lib/msun/ld128/e_lgammal_r.c b/lib/msun/ld128/e_lgammal_r.c index e3d97b6d18b7..3f23a2a7ae38 100644 --- a/lib/msun/ld128/e_lgammal_r.c +++ b/lib/msun/ld128/e_lgammal_r.c @@ -1,328 +1,327 @@ /* @(#)e_lgamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_lgamma_r.c for complete comments. * * Converted to long double by Steven G. Kargl. */ #include "fpmath.h" #include "math.h" #include "math_private.h" static const volatile double vzero = 0; static const double zero= 0, half= 0.5, one = 1; static const long double pi = 3.14159265358979323846264338327950288e+00L; /* * Domain y in [0x1p-119, 0.28], range ~[-1.4065e-36, 1.4065e-36]: * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-119.1 */ static const long double a0 = 7.72156649015328606065120900824024296e-02L, a1 = 3.22467033424113218236207583323018498e-01L, a2 = 6.73523010531980951332460538330282217e-02L, a3 = 2.05808084277845478790009252803463129e-02L, a4 = 7.38555102867398526627292839296001626e-03L, a5 = 2.89051033074152328576829509522483468e-03L, a6 = 1.19275391170326097618357349881842913e-03L, a7 = 5.09669524743042462515256340206203019e-04L, a8 = 2.23154758453578096143609255559576017e-04L, a9 = 9.94575127818397632126978731542755129e-05L, a10 = 4.49262367375420471287545895027098145e-05L, a11 = 2.05072127845117995426519671481628849e-05L, a12 = 9.43948816959096748454087141447939513e-06L, a13 = 4.37486780697359330303852050718287419e-06L, a14 = 2.03920783892362558276037363847651809e-06L, a15 = 9.55191070057967287877923073200324649e-07L, a16 = 4.48993286185740853170657139487620560e-07L, a17 = 2.13107543597620911675316728179563522e-07L, a18 = 9.70745379855304499867546549551023473e-08L, a19 = 5.61889970390290257926487734695402075e-08L, a20 = 6.42739653024130071866684358960960951e-09L, a21 = 3.34491062143649291746195612991870119e-08L, a22 = -1.57068547394315223934653011440641472e-08L, a23 = 1.30812825422415841213733487745200632e-08L; /* * Domain x in [tc-0.24, tc+0.28], range ~[-6.3201e-37, 6.3201e-37]: * |(lgamma(x) - tf) - t(x - tc)| < 2**-120.3. */ static const long double tc = 1.46163214496836234126265954232572133e+00L, tf = -1.21486290535849608095514557177691584e-01L, tt = 1.57061739945077675484237837992951704e-36L, t0 = -1.99238329499314692728655623767019240e-36L, t1 = -6.08453430711711404116887457663281416e-35L, t2 = 4.83836122723810585213722380854828904e-01L, t3 = -1.47587722994530702030955093950668275e-01L, t4 = 6.46249402389127526561003464202671923e-02L, t5 = -3.27885410884813055008502586863748063e-02L, t6 = 1.79706751152103942928638276067164935e-02L, t7 = -1.03142230366363872751602029672767978e-02L, t8 = 6.10053602051788840313573150785080958e-03L, t9 = -3.68456960831637325470641021892968954e-03L, t10 = 2.25976482322181046611440855340968560e-03L, t11 = -1.40225144590445082933490395950664961e-03L, t12 = 8.78232634717681264035014878172485575e-04L, t13 = -5.54194952796682301220684760591403899e-04L, t14 = 3.51912956837848209220421213975000298e-04L, t15 = -2.24653443695947456542669289367055542e-04L, t16 = 1.44070395420840737695611929680511823e-04L, t17 = -9.27609865550394140067059487518862512e-05L, t18 = 5.99347334438437081412945428365433073e-05L, t19 = -3.88458388854572825603964274134801009e-05L, t20 = 2.52476631610328129217896436186551043e-05L, t21 = -1.64508584981658692556994212457518536e-05L, t22 = 1.07434583475987007495523340296173839e-05L, t23 = -7.03070407519397260929482550448878399e-06L, t24 = 4.60968590693753579648385629003100469e-06L, t25 = -3.02765473778832036018438676945512661e-06L, t26 = 1.99238771545503819972741288511303401e-06L, t27 = -1.31281299822614084861868817951788579e-06L, t28 = 8.60844432267399655055574642052370223e-07L, t29 = -5.64535486432397413273248363550536374e-07L, t30 = 3.99357783676275660934903139592727737e-07L, t31 = -2.95849029193433121795495215869311610e-07L, t32 = 1.37790144435073124976696250804940384e-07L; /* * Domain y in [-0.1, 0.232], range ~[-1.4046e-37, 1.4181e-37]: * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-122.8 */ static const long double u0 = -7.72156649015328606065120900824024311e-02L, u1 = 4.24082772271938167430983113242482656e-01L, u2 = 2.96194003481457101058321977413332171e+00L, u3 = 6.49503267711258043997790983071543710e+00L, u4 = 7.40090051288150177152835698948644483e+00L, u5 = 4.94698036296756044610805900340723464e+00L, u6 = 2.00194224610796294762469550684947768e+00L, u7 = 4.82073087750608895996915051568834949e-01L, u8 = 6.46694052280506568192333848437585427e-02L, u9 = 4.17685526755100259316625348933108810e-03L, u10 = 9.06361003550314327144119307810053410e-05L, v1 = 5.15937098592887275994320496999951947e+00L, v2 = 1.14068418766251486777604403304717558e+01L, v3 = 1.41164839437524744055723871839748489e+01L, v4 = 1.07170702656179582805791063277960532e+01L, v5 = 5.14448694179047879915042998453632434e+00L, v6 = 1.55210088094585540637493826431170289e+00L, v7 = 2.82975732849424562719893657416365673e-01L, v8 = 2.86424622754753198010525786005443539e-02L, v9 = 1.35364253570403771005922441442688978e-03L, v10 = 1.91514173702398375346658943749580666e-05L, v11 = -3.25364686890242327944584691466034268e-08L; /* * Domain x in (2, 3], range ~[-1.3341e-36, 1.3536e-36]: * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-120.1 * with y = x - 2. */ static const long double s0 = -7.72156649015328606065120900824024297e-02L, s1 = 1.23221687850916448903914170805852253e-01L, s2 = 5.43673188699937239808255378293820020e-01L, s3 = 6.31998137119005233383666791176301800e-01L, s4 = 3.75885340179479850993811501596213763e-01L, s5 = 1.31572908743275052623410195011261575e-01L, s6 = 2.82528453299138685507186287149699749e-02L, s7 = 3.70262021550340817867688714880797019e-03L, s8 = 2.83374000312371199625774129290973648e-04L, s9 = 1.15091830239148290758883505582343691e-05L, s10 = 2.04203474281493971326506384646692446e-07L, s11 = 9.79544198078992058548607407635645763e-10L, r1 = 2.58037466655605285937112832039537492e+00L, r2 = 2.86289413392776399262513849911531180e+00L, r3 = 1.78691044735267497452847829579514367e+00L, r4 = 6.89400381446725342846854215600008055e-01L, r5 = 1.70135865462567955867134197595365343e-01L, r6 = 2.68794816183964420375498986152766763e-02L, r7 = 2.64617234244861832870088893332006679e-03L, r8 = 1.52881761239180800640068128681725702e-04L, r9 = 4.63264813762296029824851351257638558e-06L, r10 = 5.89461519146957343083848967333671142e-08L, r11 = 1.79027678176582527798327441636552968e-10L; /* * Domain z in [8, 0x1p70], range ~[-9.8214e-35, 9.8214e-35]: * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-113.0 */ static const long double w0 = 4.18938533204672741780329736405617738e-01L, w1 = 8.33333333333333333333333333332852026e-02L, w2 = -2.77777777777777777777777727810123528e-03L, w3 = 7.93650793650793650791708939493907380e-04L, w4 = -5.95238095238095234390450004444370959e-04L, w5 = 8.41750841750837633887817658848845695e-04L, w6 = -1.91752691752396849943172337347259743e-03L, w7 = 6.41025640880333069429106541459015557e-03L, w8 = -2.95506530801732133437990433080327074e-02L, w9 = 1.79644237328444101596766586979576927e-01L, w10 = -1.39240539108367641920172649259736394e+00L, w11 = 1.33987701479007233325288857758641761e+01L, w12 = -1.56363596431084279780966590116006255e+02L, w13 = 2.14830978044410267201172332952040777e+03L, w14 = -3.28636067474227378352761516589092334e+04L, w15 = 5.06201257747865138432663574251462485e+05L, w16 = -6.79720123352023636706247599728048344e+06L, w17 = 6.57556601705472106989497289465949255e+07L, w18 = -3.26229058141181783534257632389415580e+08L; static long double sin_pil(long double x) { volatile long double vz; long double y,z; uint64_t lx, n; uint16_t hx; y = -x; vz = y+0x1.p112; z = vz-0x1.p112; if (z == y) return zero; vz = y+0x1.p110; EXTRACT_LDBL128_WORDS(hx,lx,n,vz); z = vz-0x1.p110; if (z > y) { z -= 0.25; n--; } n &= 7; y = y - z + n * 0.25; switch (n) { case 0: y = __kernel_sinl(pi*y,zero,0); break; case 1: case 2: y = __kernel_cosl(pi*(0.5-y),zero); break; case 3: case 4: y = __kernel_sinl(pi*(one-y),zero,0); break; case 5: case 6: y = -__kernel_cosl(pi*(y-1.5),zero); break; default: y = __kernel_sinl(pi*(y-2.0),zero,0); break; } return -y; } long double lgammal_r(long double x, int *signgamp) { long double nadj,p,p1,p2,p3,q,r,t,w,y,z; uint64_t llx,lx; int i; uint16_t hx,ix; EXTRACT_LDBL128_WORDS(hx,lx,llx,x); /* purge +-Inf and NaNs */ *signgamp = 1; ix = hx&0x7fff; if(ix==0x7fff) return x*x; /* purge +-0 and tiny arguments */ *signgamp = 1-2*(hx>>15); if(ix<0x3fff-116) { /* |x|<2**-(p+3), return -log(|x|) */ if((ix|lx|llx)==0) return one/vzero; return -logl(fabsl(x)); } /* purge negative integers and start evaluation for other x < 0 */ if(hx&0x8000) { *signgamp = 1; if(ix>=0x3fff+112) /* |x|>=2**(p-1), must be -integer */ return one/vzero; t = sin_pil(x); if(t==zero) return one/vzero; nadj = logl(pi/fabsl(t*x)); if(t=7.3159980773925781e-01) {y = 1-x; i= 0;} else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;} else {y = x; i=2;} } else { r = 0; if(x>=1.7316312789916992e+00) {y=2-x;i=0;} else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;} else {y=x-1;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*(a12+z*(a14+z*(a16+ z*(a18+z*(a20+z*a22)))))))))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*(a13+z*(a15+ z*(a17+z*(a19+z*(a21+z*a23))))))))))); p = y*p1+p2; r += p-y/2; break; case 1: p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+ y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+ y*(t17+y*(t18+y*(t19+y*(t20+y*(t21+y*(t22+y*(t23+ y*(t24+y*(t25+y*(t26+y*(t27+y*(t28+y*(t29+y*(t30+ y*(t31+y*t32)))))))))))))))))))))))))))))); r += tf + p; break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*(u6+y*(u7+ y*(u8+y*(u9+y*u10)))))))))); p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*(v6+y*(v7+ y*(v8+y*(v9+y*(v10+y*v11)))))))))); r += p1/p2-y/2; } } /* x < 8.0 */ else if(ix<0x4002) { i = x; y = x-i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*(s6+y*(s7+y*(s8+ y*(s9+y*(s10+y*s11))))))))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*(r7+y*(r8+ y*(r9+y*(r10+y*r11)))))))))); r = y/2+p/q; z = 1; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+6); /* FALLTHRU */ case 6: z *= (y+5); /* FALLTHRU */ case 5: z *= (y+4); /* FALLTHRU */ case 4: z *= (y+3); /* FALLTHRU */ case 3: z *= (y+2); /* FALLTHRU */ r += logl(z); break; } /* 8.0 <= x < 2**(p+3) */ } else if (ix<0x3fff+116) { t = logl(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*(w8+ y*(w9+y*(w10+y*(w11+y*(w12+y*(w13+y*(w14+y*(w15+y*(w16+ y*(w17+y*w18))))))))))))))))); r = (x-half)*(t-one)+w; /* 2**(p+3) <= x <= inf */ } else r = x*(logl(x)-1); if(hx&0x8000) r = nadj - r; return r; } diff --git a/lib/msun/ld128/e_powl.c b/lib/msun/ld128/e_powl.c index fd8b57b66bd5..f5a993cf0054 100644 --- a/lib/msun/ld128/e_powl.c +++ b/lib/msun/ld128/e_powl.c @@ -1,441 +1,440 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * Copyright (c) 2008 Stephen L. Moshier * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* powl(x,y) return x**y * * n * Method: Let x = 2 * (1+f) * 1. Compute and return log2(x) in two pieces: * log2(x) = w1 + w2, * where w1 has 113-53 = 60 bit trailing zeros. * 2. Perform y*log2(x) = n+y' by simulating multi-precision * arithmetic, where |y'|<=0.5. * 3. Return x**y = 2**n*exp(y'*log2) * * Special cases: * 1. (anything) ** 0 is 1 * 2. (anything) ** 1 is itself * 3. (anything) ** NAN is NAN * 4. NAN ** (anything except 0) is NAN * 5. +-(|x| > 1) ** +INF is +INF * 6. +-(|x| > 1) ** -INF is +0 * 7. +-(|x| < 1) ** +INF is +0 * 8. +-(|x| < 1) ** -INF is +INF * 9. +-1 ** +-INF is NAN * 10. +0 ** (+anything except 0, NAN) is +0 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 * 12. +0 ** (-anything except 0, NAN) is +INF * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) * 15. +INF ** (+anything except 0,NAN) is +INF * 16. +INF ** (-anything except 0,NAN) is +0 * 17. -INF ** (anything) = -0 ** (-anything) * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) * 19. (-anything except 0 and inf) ** (non-integer) is NAN * */ -#include #include #include #include "math_private.h" static const long double bp[] = { 1.0L, 1.5L, }; /* log_2(1.5) */ static const long double dp_h[] = { 0.0, 5.8496250072115607565592654282227158546448E-1L }; /* Low part of log_2(1.5) */ static const long double dp_l[] = { 0.0, 1.0579781240112554492329533686862998106046E-16L }; static const long double zero = 0.0L, one = 1.0L, two = 2.0L, two113 = 1.0384593717069655257060992658440192E34L, huge = 1.0e3000L, tiny = 1.0e-3000L; /* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2)) z = (x-1)/(x+1) 1 <= x <= 1.25 Peak relative error 2.3e-37 */ static const long double LN[] = { -3.0779177200290054398792536829702930623200E1L, 6.5135778082209159921251824580292116201640E1L, -4.6312921812152436921591152809994014413540E1L, 1.2510208195629420304615674658258363295208E1L, -9.9266909031921425609179910128531667336670E-1L }; static const long double LD[] = { -5.129862866715009066465422805058933131960E1L, 1.452015077564081884387441590064272782044E2L, -1.524043275549860505277434040464085593165E2L, 7.236063513651544224319663428634139768808E1L, -1.494198912340228235853027849917095580053E1L /* 1.0E0 */ }; /* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2))) 0 <= x <= 0.5 Peak relative error 5.7e-38 */ static const long double PN[] = { 5.081801691915377692446852383385968225675E8L, 9.360895299872484512023336636427675327355E6L, 4.213701282274196030811629773097579432957E4L, 5.201006511142748908655720086041570288182E1L, 9.088368420359444263703202925095675982530E-3L, }; static const long double PD[] = { 3.049081015149226615468111430031590411682E9L, 1.069833887183886839966085436512368982758E8L, 8.259257717868875207333991924545445705394E5L, 1.872583833284143212651746812884298360922E3L, /* 1.0E0 */ }; static const long double /* ln 2 */ lg2 = 6.9314718055994530941723212145817656807550E-1L, lg2_h = 6.9314718055994528622676398299518041312695E-1L, lg2_l = 2.3190468138462996154948554638754786504121E-17L, ovt = 8.0085662595372944372e-0017L, /* 2/(3*log(2)) */ cp = 9.6179669392597560490661645400126142495110E-1L, cp_h = 9.6179669392597555432899980587535537779331E-1L, cp_l = 5.0577616648125906047157785230014751039424E-17L; long double powl(long double x, long double y) { long double z, ax, z_h, z_l, p_h, p_l; long double yy1, t1, t2, r, s, t, u, v, w; long double s2, s_h, s_l, t_h, t_l; int32_t i, j, k, yisint, n; u_int32_t ix, iy; int32_t hx, hy; ieee_quad_shape_type o, p, q; p.value = x; hx = p.parts32.mswhi; ix = hx & 0x7fffffff; q.value = y; hy = q.parts32.mswhi; iy = hy & 0x7fffffff; /* y==zero: x**0 = 1 */ if ((iy | q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0) return one; /* 1.0**y = 1; -1.0**+-Inf = 1 */ if (x == one) return one; if (x == -1.0L && iy == 0x7fff0000 && (q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0) return one; /* +-NaN return x+y */ if ((ix > 0x7fff0000) || ((ix == 0x7fff0000) && ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) != 0)) || (iy > 0x7fff0000) || ((iy == 0x7fff0000) && ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) != 0))) return nan_mix(x, y); /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if (hx < 0) { if (iy >= 0x40700000) /* 2^113 */ yisint = 2; /* even integer y */ else if (iy >= 0x3fff0000) /* 1.0 */ { if (floorl (y) == y) { z = 0.5 * y; if (floorl (z) == z) yisint = 2; else yisint = 1; } } } /* special value of y */ if ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0) { if (iy == 0x7fff0000) /* y is +-inf */ { if (((ix - 0x3fff0000) | p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) == 0) return y - y; /* +-1**inf is NaN */ else if (ix >= 0x3fff0000) /* (|x|>1)**+-inf = inf,0 */ return (hy >= 0) ? y : zero; else /* (|x|<1)**-,+inf = inf,0 */ return (hy < 0) ? -y : zero; } if (iy == 0x3fff0000) { /* y is +-1 */ if (hy < 0) return one / x; else return x; } if (hy == 0x40000000) return x * x; /* y is 2 */ if (hy == 0x3ffe0000) { /* y is 0.5 */ if (hx >= 0) /* x >= +0 */ return sqrtl (x); } } ax = fabsl (x); /* special value of x */ if ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) == 0) { if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000) { z = ax; /*x is +-0,+-inf,+-1 */ if (hy < 0) z = one / z; /* z = (1/|x|) */ if (hx < 0) { if (((ix - 0x3fff0000) | yisint) == 0) { z = (z - z) / (z - z); /* (-1)**non-int is NaN */ } else if (yisint == 1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } } /* (x<0)**(non-int) is NaN */ if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0) return (x - x) / (x - x); /* |y| is huge. 2^-16495 = 1/2 of smallest representable value. If (1 - 1/131072)^y underflows, y > 1.4986e9 */ if (iy > 0x401d654b) { /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */ if (iy > 0x407d654b) { if (ix <= 0x3ffeffff) return (hy < 0) ? huge * huge : tiny * tiny; if (ix >= 0x3fff0000) return (hy > 0) ? huge * huge : tiny * tiny; } /* over/underflow if x is not close to one */ if (ix < 0x3ffeffff) return (hy < 0) ? huge * huge : tiny * tiny; if (ix > 0x3fff0000) return (hy > 0) ? huge * huge : tiny * tiny; } n = 0; /* take care subnormal number */ if (ix < 0x00010000) { ax *= two113; n -= 113; o.value = ax; ix = o.parts32.mswhi; } n += ((ix) >> 16) - 0x3fff; j = ix & 0x0000ffff; /* determine interval */ ix = j | 0x3fff0000; /* normalize ix */ if (j <= 0x3988) k = 0; /* |x|> 31) - 1) | (yisint - 1)) == 0) s = -one; /* (-ve)**(odd int) */ /* split up y into yy1+y2 and compute (yy1+y2)*(t1+t2) */ yy1 = y; o.value = yy1; o.parts32.lswlo = 0; o.parts32.lswhi &= 0xf8000000; yy1 = o.value; p_l = (y - yy1) * t1 + y * t2; p_h = yy1 * t1; z = p_l + p_h; o.value = z; j = o.parts32.mswhi; if (j >= 0x400d0000) /* z >= 16384 */ { /* if z > 16384 */ if (((j - 0x400d0000) | o.parts32.mswlo | o.parts32.lswhi | o.parts32.lswlo) != 0) return s * huge * huge; /* overflow */ else { if (p_l + ovt > z - p_h) return s * huge * huge; /* overflow */ } } else if ((j & 0x7fffffff) >= 0x400d01b9) /* z <= -16495 */ { /* z < -16495 */ if (((j - 0xc00d01bc) | o.parts32.mswlo | o.parts32.lswhi | o.parts32.lswlo) != 0) return s * tiny * tiny; /* underflow */ else { if (p_l <= z - p_h) return s * tiny * tiny; /* underflow */ } } /* compute 2**(p_h+p_l) */ i = j & 0x7fffffff; k = (i >> 16) - 0x3fff; n = 0; if (i > 0x3ffe0000) { /* if |z| > 0.5, set n = [z+0.5] */ n = floorl (z + 0.5L); t = n; p_h -= t; } t = p_l + p_h; o.value = t; o.parts32.lswlo = 0; o.parts32.lswhi &= 0xf8000000; t = o.value; u = t * lg2_h; v = (p_l - (t - p_h)) * lg2 + t * lg2_l; z = u + v; w = v - (z - u); /* exp(z) */ t = z * z; u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4]))); v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t))); t1 = z - t * u / v; r = (z * t1) / (t1 - two) - (w + z * w); z = one - (r - z); o.value = z; j = o.parts32.mswhi; j += (n << 16); if ((j >> 16) <= 0) z = scalbnl (z, n); /* subnormal output */ else { o.parts32.mswhi = j; z = o.value; } return s * z; } diff --git a/lib/msun/ld128/e_rem_pio2l.h b/lib/msun/ld128/e_rem_pio2l.h index 35ed0b865a7c..5d1f9bde92da 100644 --- a/lib/msun/ld128/e_rem_pio2l.h +++ b/lib/msun/ld128/e_rem_pio2l.h @@ -1,133 +1,132 @@ /* From: @(#)e_rem_pio2.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * Optimized by Bruce D. Evans. */ -#include /* ld128 version of __ieee754_rem_pio2l(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __kernel_rem_pio2() */ #include #include "math.h" #include "math_private.h" #include "fpmath.h" #define BIAS (LDBL_MAX_EXP - 1) /* * XXX need to verify that nonzero integer multiples of pi/2 within the * range get no closer to a long double than 2**-140, or that * ilogb(x) + ilogb(min_delta) < 45 - -140. */ /* * invpio2: 113 bits of 2/pi * pio2_1: first 68 bits of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 68 bits of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 68 bits of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ two24 = 1.67772160000000000000e+07; /* 0x41700000, 0x00000000 */ static const long double invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */ pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */ pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */ pio2_2 = 2.0222662487959507323994779168837751e-21L, /* 0x13198a2e03707344a400000000000.0p-181 */ pio2_2t = 2.0670321098263988236496903051604844e-43L, /* 0x127044533e63a0105df531d89cd91.0p-254 */ pio2_3 = 2.0670321098263988236499468110329591e-43L, /* 0x127044533e63a0105e00000000000.0p-254 */ pio2_3t = -2.5650587247459238361625433492959285e-65L; /* -0x159c4ec64ddaeb5f78671cbfb2210.0p-327 */ static inline __always_inline int __ieee754_rem_pio2l(long double x, long double *y) { union IEEEl2bits u,u1; long double z,w,t,r,fn; double tx[5],ty[3]; int64_t n; int e0,ex,i,j,nx; int16_t expsign; u.e = x; expsign = u.xbits.expsign; ex = expsign & 0x7fff; if (ex < BIAS + 45 || ex == BIAS + 45 && u.bits.manh < 0x921fb54442d1LL) { /* |x| ~< 2^45*(pi/2), medium size */ /* TODO: use only double precision for fn, as in expl(). */ fn = rnintl(x * invpio2); n = i64rint(fn); r = x-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 180 bit */ { union IEEEl2bits u2; int ex1; j = ex; y[0] = r-w; u2.e = y[0]; ex1 = u2.xbits.expsign & 0x7fff; i = j-ex1; if(i>51) { /* 2nd iteration needed, good to 248 */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; u2.e = y[0]; ex1 = u2.xbits.expsign & 0x7fff; i = j-ex1; if(i>119) { /* 3rd iteration need, 316 bits acc */ t = r; /* will cover all possible cases */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); y[0] = r-w; } } } y[1] = (r-y[0])-w; return n; } /* * all other (large) arguments */ if(ex==0x7fff) { /* x is inf or NaN */ y[0]=y[1]=x-x; return 0; } /* set z = scalbn(|x|,ilogb(x)-23) */ u1.e = x; e0 = ex - BIAS - 23; /* e0 = ilogb(|x|)-23; */ u1.xbits.expsign = ex - e0; z = u1.e; for(i=0;i<4;i++) { tx[i] = (double)((int32_t)(z)); z = (z-tx[i])*two24; } tx[4] = z; nx = 5; while(tx[nx-1]==zero) nx--; /* skip zero term */ n = __kernel_rem_pio2(tx,ty,e0,nx,3); t = (long double)ty[2] + ty[1]; r = t + ty[0]; w = ty[0] - (r - t); if(expsign<0) {y[0] = -r; y[1] = -w; return -n;} y[0] = r; y[1] = w; return n; } diff --git a/lib/msun/ld128/invtrig.c b/lib/msun/ld128/invtrig.c index cd9a276b68d1..75aef7b5166a 100644 --- a/lib/msun/ld128/invtrig.c +++ b/lib/msun/ld128/invtrig.c @@ -1,100 +1,99 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include "invtrig.h" /* * asinl() and acosl() */ const long double pS0 = 1.66666666666666666666666666666700314e-01L, pS1 = -7.32816946414566252574527475428622708e-01L, pS2 = 1.34215708714992334609030036562143589e+00L, pS3 = -1.32483151677116409805070261790752040e+00L, pS4 = 7.61206183613632558824485341162121989e-01L, pS5 = -2.56165783329023486777386833928147375e-01L, pS6 = 4.80718586374448793411019434585413855e-02L, pS7 = -4.42523267167024279410230886239774718e-03L, pS8 = 1.44551535183911458253205638280410064e-04L, pS9 = -2.10558957916600254061591040482706179e-07L, qS1 = -4.84690167848739751544716485245697428e+00L, qS2 = 9.96619113536172610135016921140206980e+00L, qS3 = -1.13177895428973036660836798461641458e+01L, qS4 = 7.74004374389488266169304117714658761e+00L, qS5 = -3.25871986053534084709023539900339905e+00L, qS6 = 8.27830318881232209752469022352928864e-01L, qS7 = -1.18768052702942805423330715206348004e-01L, qS8 = 8.32600764660522313269101537926539470e-03L, qS9 = -1.99407384882605586705979504567947007e-04L; /* * atanl() */ const long double atanhi[] = { 4.63647609000806116214256231461214397e-01L, 7.85398163397448309615660845819875699e-01L, 9.82793723247329067985710611014666038e-01L, 1.57079632679489661923132169163975140e+00L, }; const long double atanlo[] = { 4.89509642257333492668618435220297706e-36L, 2.16795253253094525619926100651083806e-35L, -2.31288434538183565909319952098066272e-35L, 4.33590506506189051239852201302167613e-35L, }; const long double aT[] = { 3.33333333333333333333333333333333125e-01L, -1.99999999999999999999999999999180430e-01L, 1.42857142857142857142857142125269827e-01L, -1.11111111111111111111110834490810169e-01L, 9.09090909090909090908522355708623681e-02L, -7.69230769230769230696553844935357021e-02L, 6.66666666666666660390096773046256096e-02L, -5.88235294117646671706582985209643694e-02L, 5.26315789473666478515847092020327506e-02L, -4.76190476189855517021024424991436144e-02L, 4.34782608678695085948531993458097026e-02L, -3.99999999632663469330634215991142368e-02L, 3.70370363987423702891250829918659723e-02L, -3.44827496515048090726669907612335954e-02L, 3.22579620681420149871973710852268528e-02L, -3.03020767654269261041647570626778067e-02L, 2.85641979882534783223403715930946138e-02L, -2.69824879726738568189929461383741323e-02L, 2.54194698498808542954187110873675769e-02L, -2.35083879708189059926183138130183215e-02L, 2.04832358998165364349957325067131428e-02L, -1.54489555488544397858507248612362957e-02L, 8.64492360989278761493037861575248038e-03L, -2.58521121597609872727919154569765469e-03L, }; const long double pi_lo = 8.67181013012378102479704402604335225e-35L; diff --git a/lib/msun/ld128/k_cosl.c b/lib/msun/ld128/k_cosl.c index 8280378c429c..7b5f0c60fbb3 100644 --- a/lib/msun/ld128/k_cosl.c +++ b/lib/msun/ld128/k_cosl.c @@ -1,57 +1,56 @@ /* From: @(#)k_cos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld128 version of k_cos.c. See ../src/k_cos.c for most comments. */ #include "math_private.h" /* * Domain [-0.7854, 0.7854], range ~[-1.17e-39, 1.19e-39]: * |cos(x) - c(x))| < 2**-129.3 * * 113-bit precision requires more care than 64-bit precision, since * simple methods give a minimax polynomial with coefficient for x^2 * that is 1 ulp below 0.5, but we want it to be precisely 0.5. See * ../ld80/k_cosl.c for more details. */ static const double one = 1.0; static const long double C1 = 4.16666666666666666666666666666666667e-02L, C2 = -1.38888888888888888888888888888888834e-03L, C3 = 2.48015873015873015873015873015446795e-05L, C4 = -2.75573192239858906525573190949988493e-07L, C5 = 2.08767569878680989792098886701451072e-09L, C6 = -1.14707455977297247136657111139971865e-11L, C7 = 4.77947733238738518870113294139830239e-14L, C8 = -1.56192069685858079920640872925306403e-16L, C9 = 4.11031762320473354032038893429515732e-19L, C10= -8.89679121027589608738005163931958096e-22L, C11= 1.61171797801314301767074036661901531e-24L, C12= -2.46748624357670948912574279501044295e-27L; long double __kernel_cosl(long double x, long double y) { long double hz,z,r,w; z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*(C7+ z*(C8+z*(C9+z*(C10+z*(C11+z*C12))))))))))); hz = 0.5*z; w = one-hz; return w + (((one-w)-hz) + (z*r-x*y)); } diff --git a/lib/msun/ld128/k_expl.h b/lib/msun/ld128/k_expl.h index 71924f16c8a4..86811dd8e089 100644 --- a/lib/msun/ld128/k_expl.h +++ b/lib/msun/ld128/k_expl.h @@ -1,322 +1,321 @@ /* from: FreeBSD: head/lib/msun/ld128/s_expl.c 251345 2013-06-03 20:09:22Z kargl */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009-2013 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Optimized by Bruce D. Evans. */ -#include /* * ld128 version of k_expl.h. See ../ld80/s_expl.c for most comments. * * See ../src/e_exp.c and ../src/k_exp.h for precision-independent comments * about the secondary kernels. */ #define INTERVALS 128 #define LOG2_INTERVALS 7 #define BIAS (LDBL_MAX_EXP - 1) static const double /* * ln2/INTERVALS = L1+L2 (hi+lo decomposition for multiplication). L1 must * have at least 22 (= log2(|LDBL_MIN_EXP-extras|) + log2(INTERVALS)) lowest * bits zero so that multiplication of it by n is exact. */ INV_L = 1.8466496523378731e+2, /* 0x171547652b82fe.0p-45 */ L2 = -1.0253670638894731e-29; /* -0x1.9ff0342542fc3p-97 */ static const long double /* 0x1.62e42fefa39ef35793c768000000p-8 */ L1 = 5.41521234812457272982212595914567508e-3L; /* * XXX values in hex in comments have been lost (or were never present) * from here. */ static const long double /* * Domain [-0.002708, 0.002708], range ~[-2.4021e-38, 2.4234e-38]: * |exp(x) - p(x)| < 2**-124.9 * (0.002708 is ln2/(2*INTERVALS) rounded up a little). * * XXX the coeffs aren't very carefully rounded, and I get 3.6 more bits. */ A2 = 0.5, A3 = 1.66666666666666666666666666651085500e-1L, A4 = 4.16666666666666666666666666425885320e-2L, A5 = 8.33333333333333333334522877160175842e-3L, A6 = 1.38888888888888888889971139751596836e-3L; static const double A7 = 1.9841269841269470e-4, /* 0x1.a01a01a019f91p-13 */ A8 = 2.4801587301585286e-5, /* 0x1.71de3ec75a967p-19 */ A9 = 2.7557324277411235e-6, /* 0x1.71de3ec75a967p-19 */ A10 = 2.7557333722375069e-7; /* 0x1.27e505ab56259p-22 */ static const struct { /* * hi must be rounded to at most 106 bits so that multiplication * by r1 in expm1l() is exact, but it is rounded to 88 bits due to * historical accidents. * * XXX it is wasteful to use long double for both hi and lo. ld128 * exp2l() uses only float for lo (in a very differently organized * table; ld80 exp2l() is different again. It uses 2 doubles in a * table organized like this one. 1 double and 1 float would * suffice). There are different packing/locality/alignment/caching * problems with these methods. * * XXX C's bad %a format makes the bits unreadable. They happen * to all line up for the hi values 1 before the point and 88 * in 22 nybbles, but for the low values the nybbles are shifted * randomly. */ long double hi; long double lo; } tbl[INTERVALS] = { 0x1p0L, 0x0p0L, 0x1.0163da9fb33356d84a66aep0L, 0x3.36dcdfa4003ec04c360be2404078p-92L, 0x1.02c9a3e778060ee6f7cacap0L, 0x4.f7a29bde93d70a2cabc5cb89ba10p-92L, 0x1.04315e86e7f84bd738f9a2p0L, 0xd.a47e6ed040bb4bfc05af6455e9b8p-96L, 0x1.059b0d31585743ae7c548ep0L, 0xb.68ca417fe53e3495f7df4baf84a0p-92L, 0x1.0706b29ddf6ddc6dc403a8p0L, 0x1.d87b27ed07cb8b092ac75e311753p-88L, 0x1.0874518759bc808c35f25cp0L, 0x1.9427fa2b041b2d6829d8993a0d01p-88L, 0x1.09e3ecac6f3834521e060cp0L, 0x5.84d6b74ba2e023da730e7fccb758p-92L, 0x1.0b5586cf9890f6298b92b6p0L, 0x1.1842a98364291408b3ceb0a2a2bbp-88L, 0x1.0cc922b7247f7407b705b8p0L, 0x9.3dc5e8aac564e6fe2ef1d431fd98p-92L, 0x1.0e3ec32d3d1a2020742e4ep0L, 0x1.8af6a552ac4b358b1129e9f966a4p-88L, 0x1.0fb66affed31af232091dcp0L, 0x1.8a1426514e0b627bda694a400a27p-88L, 0x1.11301d0125b50a4ebbf1aep0L, 0xd.9318ceac5cc47ab166ee57427178p-92L, 0x1.12abdc06c31cbfb92bad32p0L, 0x4.d68e2f7270bdf7cedf94eb1cb818p-92L, 0x1.1429aaea92ddfb34101942p0L, 0x1.b2586d01844b389bea7aedd221d4p-88L, 0x1.15a98c8a58e512480d573cp0L, 0x1.d5613bf92a2b618ee31b376c2689p-88L, 0x1.172b83c7d517adcdf7c8c4p0L, 0x1.0eb14a792035509ff7d758693f24p-88L, 0x1.18af9388c8de9bbbf70b9ap0L, 0x3.c2505c97c0102e5f1211941d2840p-92L, 0x1.1a35beb6fcb753cb698f68p0L, 0x1.2d1c835a6c30724d5cfae31b84e5p-88L, 0x1.1bbe084045cd39ab1e72b4p0L, 0x4.27e35f9acb57e473915519a1b448p-92L, 0x1.1d4873168b9aa7805b8028p0L, 0x9.90f07a98b42206e46166cf051d70p-92L, 0x1.1ed5022fcd91cb8819ff60p0L, 0x1.121d1e504d36c47474c9b7de6067p-88L, 0x1.2063b88628cd63b8eeb028p0L, 0x1.50929d0fc487d21c2b84004264dep-88L, 0x1.21f49917ddc962552fd292p0L, 0x9.4bdb4b61ea62477caa1dce823ba0p-92L, 0x1.2387a6e75623866c1fadb0p0L, 0x1.c15cb593b0328566902df69e4de2p-88L, 0x1.251ce4fb2a63f3582ab7dep0L, 0x9.e94811a9c8afdcf796934bc652d0p-92L, 0x1.26b4565e27cdd257a67328p0L, 0x1.d3b249dce4e9186ddd5ff44e6b08p-92L, 0x1.284dfe1f5638096cf15cf0p0L, 0x3.ca0967fdaa2e52d7c8106f2e262cp-92L, 0x1.29e9df51fdee12c25d15f4p0L, 0x1.a24aa3bca890ac08d203fed80a07p-88L, 0x1.2b87fd0dad98ffddea4652p0L, 0x1.8fcab88442fdc3cb6de4519165edp-88L, 0x1.2d285a6e4030b40091d536p0L, 0xd.075384589c1cd1b3e4018a6b1348p-92L, 0x1.2ecafa93e2f5611ca0f45cp0L, 0x1.523833af611bdcda253c554cf278p-88L, 0x1.306fe0a31b7152de8d5a46p0L, 0x3.05c85edecbc27343629f502f1af2p-92L, 0x1.32170fc4cd8313539cf1c2p0L, 0x1.008f86dde3220ae17a005b6412bep-88L, 0x1.33c08b26416ff4c9c8610cp0L, 0x1.96696bf95d1593039539d94d662bp-88L, 0x1.356c55f929ff0c94623476p0L, 0x3.73af38d6d8d6f9506c9bbc93cbc0p-92L, 0x1.371a7373aa9caa7145502ep0L, 0x1.4547987e3e12516bf9c699be432fp-88L, 0x1.38cae6d05d86585a9cb0d8p0L, 0x1.bed0c853bd30a02790931eb2e8f0p-88L, 0x1.3a7db34e59ff6ea1bc9298p0L, 0x1.e0a1d336163fe2f852ceeb134067p-88L, 0x1.3c32dc313a8e484001f228p0L, 0xb.58f3775e06ab66353001fae9fca0p-92L, 0x1.3dea64c12342235b41223ep0L, 0x1.3d773fba2cb82b8244267c54443fp-92L, 0x1.3fa4504ac801ba0bf701aap0L, 0x4.1832fb8c1c8dbdff2c49909e6c60p-92L, 0x1.4160a21f72e29f84325b8ep0L, 0x1.3db61fb352f0540e6ba05634413ep-88L, 0x1.431f5d950a896dc7044394p0L, 0x1.0ccec81e24b0caff7581ef4127f7p-92L, 0x1.44e086061892d03136f408p0L, 0x1.df019fbd4f3b48709b78591d5cb5p-88L, 0x1.46a41ed1d005772512f458p0L, 0x1.229d97df404ff21f39c1b594d3a8p-88L, 0x1.486a2b5c13cd013c1a3b68p0L, 0x1.062f03c3dd75ce8757f780e6ec99p-88L, 0x1.4a32af0d7d3de672d8bcf4p0L, 0x6.f9586461db1d878b1d148bd3ccb8p-92L, 0x1.4bfdad5362a271d4397afep0L, 0xc.42e20e0363ba2e159c579f82e4b0p-92L, 0x1.4dcb299fddd0d63b36ef1ap0L, 0x9.e0cc484b25a5566d0bd5f58ad238p-92L, 0x1.4f9b2769d2ca6ad33d8b68p0L, 0x1.aa073ee55e028497a329a7333dbap-88L, 0x1.516daa2cf6641c112f52c8p0L, 0x4.d822190e718226177d7608d20038p-92L, 0x1.5342b569d4f81df0a83c48p0L, 0x1.d86a63f4e672a3e429805b049465p-88L, 0x1.551a4ca5d920ec52ec6202p0L, 0x4.34ca672645dc6c124d6619a87574p-92L, 0x1.56f4736b527da66ecb0046p0L, 0x1.64eb3c00f2f5ab3d801d7cc7272dp-88L, 0x1.58d12d497c7fd252bc2b72p0L, 0x1.43bcf2ec936a970d9cc266f0072fp-88L, 0x1.5ab07dd48542958c930150p0L, 0x1.91eb345d88d7c81280e069fbdb63p-88L, 0x1.5c9268a5946b701c4b1b80p0L, 0x1.6986a203d84e6a4a92f179e71889p-88L, 0x1.5e76f15ad21486e9be4c20p0L, 0x3.99766a06548a05829e853bdb2b52p-92L, 0x1.605e1b976dc08b076f592ap0L, 0x4.86e3b34ead1b4769df867b9c89ccp-92L, 0x1.6247eb03a5584b1f0fa06ep0L, 0x1.d2da42bb1ceaf9f732275b8aef30p-88L, 0x1.6434634ccc31fc76f8714cp0L, 0x4.ed9a4e41000307103a18cf7a6e08p-92L, 0x1.66238825522249127d9e28p0L, 0x1.b8f314a337f4dc0a3adf1787ff74p-88L, 0x1.68155d44ca973081c57226p0L, 0x1.b9f32706bfe4e627d809a85dcc66p-88L, 0x1.6a09e667f3bcc908b2fb12p0L, 0x1.66ea957d3e3adec17512775099dap-88L, 0x1.6c012750bdabeed76a9980p0L, 0xf.4f33fdeb8b0ecd831106f57b3d00p-96L, 0x1.6dfb23c651a2ef220e2cbep0L, 0x1.bbaa834b3f11577ceefbe6c1c411p-92L, 0x1.6ff7df9519483cf87e1b4ep0L, 0x1.3e213bff9b702d5aa477c12523cep-88L, 0x1.71f75e8ec5f73dd2370f2ep0L, 0xf.0acd6cb434b562d9e8a20adda648p-92L, 0x1.73f9a48a58173bd5c9a4e6p0L, 0x8.ab1182ae217f3a7681759553e840p-92L, 0x1.75feb564267c8bf6e9aa32p0L, 0x1.a48b27071805e61a17b954a2dad8p-88L, 0x1.780694fde5d3f619ae0280p0L, 0x8.58b2bb2bdcf86cd08e35fb04c0f0p-92L, 0x1.7a11473eb0186d7d51023ep0L, 0x1.6cda1f5ef42b66977960531e821bp-88L, 0x1.7c1ed0130c1327c4933444p0L, 0x1.937562b2dc933d44fc828efd4c9cp-88L, 0x1.7e2f336cf4e62105d02ba0p0L, 0x1.5797e170a1427f8fcdf5f3906108p-88L, 0x1.80427543e1a11b60de6764p0L, 0x9.a354ea706b8e4d8b718a672bf7c8p-92L, 0x1.82589994cce128acf88afap0L, 0xb.34a010f6ad65cbbac0f532d39be0p-92L, 0x1.8471a4623c7acce52f6b96p0L, 0x1.c64095370f51f48817914dd78665p-88L, 0x1.868d99b4492ec80e41d90ap0L, 0xc.251707484d73f136fb5779656b70p-92L, 0x1.88ac7d98a669966530bcdep0L, 0x1.2d4e9d61283ef385de170ab20f96p-88L, 0x1.8ace5422aa0db5ba7c55a0p0L, 0x1.92c9bb3e6ed61f2733304a346d8fp-88L, 0x1.8cf3216b5448bef2aa1cd0p0L, 0x1.61c55d84a9848f8c453b3ca8c946p-88L, 0x1.8f1ae991577362b982745cp0L, 0x7.2ed804efc9b4ae1458ae946099d4p-92L, 0x1.9145b0b91ffc588a61b468p0L, 0x1.f6b70e01c2a90229a4c4309ea719p-88L, 0x1.93737b0cdc5e4f4501c3f2p0L, 0x5.40a22d2fc4af581b63e8326efe9cp-92L, 0x1.95a44cbc8520ee9b483694p0L, 0x1.a0fc6f7c7d61b2b3a22a0eab2cadp-88L, 0x1.97d829fde4e4f8b9e920f8p0L, 0x1.1e8bd7edb9d7144b6f6818084cc7p-88L, 0x1.9a0f170ca07b9ba3109b8cp0L, 0x4.6737beb19e1eada6825d3c557428p-92L, 0x1.9c49182a3f0901c7c46b06p0L, 0x1.1f2be58ddade50c217186c90b457p-88L, 0x1.9e86319e323231824ca78ep0L, 0x6.4c6e010f92c082bbadfaf605cfd4p-92L, 0x1.a0c667b5de564b29ada8b8p0L, 0xc.ab349aa0422a8da7d4512edac548p-92L, 0x1.a309bec4a2d3358c171f76p0L, 0x1.0daad547fa22c26d168ea762d854p-88L, 0x1.a5503b23e255c8b424491cp0L, 0xa.f87bc8050a405381703ef7caff50p-92L, 0x1.a799e1330b3586f2dfb2b0p0L, 0x1.58f1a98796ce8908ae852236ca94p-88L, 0x1.a9e6b5579fdbf43eb243bcp0L, 0x1.ff4c4c58b571cf465caf07b4b9f5p-88L, 0x1.ac36bbfd3f379c0db966a2p0L, 0x1.1265fc73e480712d20f8597a8e7bp-88L, 0x1.ae89f995ad3ad5e8734d16p0L, 0x1.73205a7fbc3ae675ea440b162d6cp-88L, 0x1.b0e07298db66590842acdep0L, 0x1.c6f6ca0e5dcae2aafffa7a0554cbp-88L, 0x1.b33a2b84f15faf6bfd0e7ap0L, 0x1.d947c2575781dbb49b1237c87b6ep-88L, 0x1.b59728de559398e3881110p0L, 0x1.64873c7171fefc410416be0a6525p-88L, 0x1.b7f76f2fb5e46eaa7b081ap0L, 0xb.53c5354c8903c356e4b625aacc28p-92L, 0x1.ba5b030a10649840cb3c6ap0L, 0xf.5b47f297203757e1cc6eadc8bad0p-92L, 0x1.bcc1e904bc1d2247ba0f44p0L, 0x1.b3d08cd0b20287092bd59be4ad98p-88L, 0x1.bf2c25bd71e088408d7024p0L, 0x1.18e3449fa073b356766dfb568ff4p-88L, 0x1.c199bdd85529c2220cb12ap0L, 0x9.1ba6679444964a36661240043970p-96L, 0x1.c40ab5fffd07a6d14df820p0L, 0xf.1828a5366fd387a7bdd54cdf7300p-92L, 0x1.c67f12e57d14b4a2137fd2p0L, 0xf.2b301dd9e6b151a6d1f9d5d5f520p-96L, 0x1.c8f6d9406e7b511acbc488p0L, 0x5.c442ddb55820171f319d9e5076a8p-96L, 0x1.cb720dcef90691503cbd1ep0L, 0x9.49db761d9559ac0cb6dd3ed599e0p-92L, 0x1.cdf0b555dc3f9c44f8958ep0L, 0x1.ac51be515f8c58bdfb6f5740a3a4p-88L, 0x1.d072d4a07897b8d0f22f20p0L, 0x1.a158e18fbbfc625f09f4cca40874p-88L, 0x1.d2f87080d89f18ade12398p0L, 0x9.ea2025b4c56553f5cdee4c924728p-92L, 0x1.d5818dcfba48725da05aeap0L, 0x1.66e0dca9f589f559c0876ff23830p-88L, 0x1.d80e316c98397bb84f9d04p0L, 0x8.805f84bec614de269900ddf98d28p-92L, 0x1.da9e603db3285708c01a5ap0L, 0x1.6d4c97f6246f0ec614ec95c99392p-88L, 0x1.dd321f301b4604b695de3cp0L, 0x6.30a393215299e30d4fb73503c348p-96L, 0x1.dfc97337b9b5eb968cac38p0L, 0x1.ed291b7225a944efd5bb5524b927p-88L, 0x1.e264614f5a128a12761fa0p0L, 0x1.7ada6467e77f73bf65e04c95e29dp-88L, 0x1.e502ee78b3ff6273d13014p0L, 0x1.3991e8f49659e1693be17ae1d2f9p-88L, 0x1.e7a51fbc74c834b548b282p0L, 0x1.23786758a84f4956354634a416cep-88L, 0x1.ea4afa2a490d9858f73a18p0L, 0xf.5db301f86dea20610ceee13eb7b8p-92L, 0x1.ecf482d8e67f08db0312fap0L, 0x1.949cef462010bb4bc4ce72a900dfp-88L, 0x1.efa1bee615a27771fd21a8p0L, 0x1.2dac1f6dd5d229ff68e46f27e3dfp-88L, 0x1.f252b376bba974e8696fc2p0L, 0x1.6390d4c6ad5476b5162f40e1d9a9p-88L, 0x1.f50765b6e4540674f84b76p0L, 0x2.862baff99000dfc4352ba29b8908p-92L, 0x1.f7bfdad9cbe138913b4bfep0L, 0x7.2bd95c5ce7280fa4d2344a3f5618p-92L, 0x1.fa7c1819e90d82e90a7e74p0L, 0xb.263c1dc060c36f7650b4c0f233a8p-92L, 0x1.fd3c22b8f71f10975ba4b2p0L, 0x1.2bcf3a5e12d269d8ad7c1a4a8875p-88L }; /* * Kernel for expl(x). x must be finite and not tiny or huge. * "tiny" is anything that would make us underflow (|A6*x^6| < ~LDBL_MIN). * "huge" is anything that would make fn*L1 inexact (|x| > ~2**17*ln2). */ static inline void __k_expl(long double x, long double *hip, long double *lop, int *kp) { long double q, r, r1, t; double dr, fn, r2; int n, n2; /* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */ fn = rnint((double)x * INV_L); n = irint(fn); n2 = (unsigned)n % INTERVALS; /* Depend on the sign bit being propagated: */ *kp = n >> LOG2_INTERVALS; r1 = x - fn * L1; r2 = fn * -L2; r = r1 + r2; /* Evaluate expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */ dr = r; q = r2 + r * r * (A2 + r * (A3 + r * (A4 + r * (A5 + r * (A6 + dr * (A7 + dr * (A8 + dr * (A9 + dr * A10)))))))); t = tbl[n2].lo + tbl[n2].hi; *hip = tbl[n2].hi; *lop = tbl[n2].lo + t * (q + r1); } /* * XXX: the rest of the functions are identical for ld80 and ld128. * However, we should use scalbnl() for ld128, since long double * multiplication was very slow on sparc64 and no new evaluation has * been made for aarch64 and/or riscv. */ static inline void k_hexpl(long double x, long double *hip, long double *lop) { float twopkm1; int k; __k_expl(x, hip, lop, &k); SET_FLOAT_WORD(twopkm1, 0x3f800000 + ((k - 1) << 23)); *hip *= twopkm1; *lop *= twopkm1; } static inline long double hexpl(long double x) { long double hi, lo, twopkm2; int k; twopkm2 = 1; __k_expl(x, &hi, &lo, &k); SET_LDBL_EXPSIGN(twopkm2, BIAS + k - 2); return (lo + hi) * 2 * twopkm2; } #ifdef _COMPLEX_H /* * See ../src/k_exp.c for details. */ static inline long double complex __ldexp_cexpl(long double complex z, int expt) { long double c, exp_x, hi, lo, s; long double x, y, scale1, scale2; int half_expt, k; x = creall(z); y = cimagl(z); __k_expl(x, &hi, &lo, &k); exp_x = (lo + hi) * 0x1p16382L; expt += k - 16382; scale1 = 1; half_expt = expt / 2; SET_LDBL_EXPSIGN(scale1, BIAS + half_expt); scale2 = 1; SET_LDBL_EXPSIGN(scale2, BIAS + expt - half_expt); sincosl(y, &s, &c); return (CMPLXL(c * exp_x * scale1 * scale2, s * exp_x * scale1 * scale2)); } #endif /* _COMPLEX_H */ diff --git a/lib/msun/ld128/k_sinl.c b/lib/msun/ld128/k_sinl.c index ca54f9f1a630..eb458e974ae0 100644 --- a/lib/msun/ld128/k_sinl.c +++ b/lib/msun/ld128/k_sinl.c @@ -1,57 +1,56 @@ /* From: @(#)k_sin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld128 version of k_sin.c. See ../src/k_sin.c for most comments. */ #include "math_private.h" static const double half = 0.5; /* * Domain [-0.7854, 0.7854], range ~[-1.53e-37, 1.659e-37] * |sin(x)/x - s(x)| < 2**-122.1 * * See ../ld80/k_cosl.c for more details about the polynomial. */ static const long double S1 = -0.16666666666666666666666666666666666606732416116558L, S2 = 0.0083333333333333333333333333333331135404851288270047L, S3 = -0.00019841269841269841269841269839935785325638310428717L, S4 = 0.27557319223985890652557316053039946268333231205686e-5L, S5 = -0.25052108385441718775048214826384312253862930064745e-7L, S6 = 0.16059043836821614596571832194524392581082444805729e-9L, S7 = -0.76471637318198151807063387954939213287488216303768e-12L, S8 = 0.28114572543451292625024967174638477283187397621303e-14L; static const double S9 = -0.82206352458348947812512122163446202498005154296863e-17, S10 = 0.19572940011906109418080609928334380560135358385256e-19, S11 = -0.38680813379701966970673724299207480965452616911420e-22, S12 = 0.64038150078671872796678569586315881020659912139412e-25; long double __kernel_sinl(long double x, long double y, int iy) { long double z,r,v; z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*(S8+ z*(S9+z*(S10+z*(S11+z*S12))))))))); if(iy==0) return x+v*(S1+z*r); else return x-((z*(half*y-v*r)-y)-v*S1); } diff --git a/lib/msun/ld128/k_tanl.c b/lib/msun/ld128/k_tanl.c index daff6b2bde8c..62e8b8648c44 100644 --- a/lib/msun/ld128/k_tanl.c +++ b/lib/msun/ld128/k_tanl.c @@ -1,117 +1,116 @@ /* From: @(#)k_tan.c 1.5 04/04/22 SMI */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld128 version of k_tan.c. See ../src/k_tan.c for most comments. */ #include "math.h" #include "math_private.h" /* * Domain [-0.67434, 0.67434], range ~[-3.37e-36, 1.982e-37] * |tan(x)/x - t(x)| < 2**-117.8 (XXX should be ~1e-37) * * See ../ld80/k_cosl.c for more details about the polynomial. */ static const long double T3 = 0x1.5555555555555555555555555553p-2L, T5 = 0x1.1111111111111111111111111eb5p-3L, T7 = 0x1.ba1ba1ba1ba1ba1ba1ba1b694cd6p-5L, T9 = 0x1.664f4882c10f9f32d6bbe09d8bcdp-6L, T11 = 0x1.226e355e6c23c8f5b4f5762322eep-7L, T13 = 0x1.d6d3d0e157ddfb5fed8e84e27b37p-9L, T15 = 0x1.7da36452b75e2b5fce9ee7c2c92ep-10L, T17 = 0x1.355824803674477dfcf726649efep-11L, T19 = 0x1.f57d7734d1656e0aceb716f614c2p-13L, T21 = 0x1.967e18afcb180ed942dfdc518d6cp-14L, T23 = 0x1.497d8eea21e95bc7e2aa79b9f2cdp-15L, T25 = 0x1.0b132d39f055c81be49eff7afd50p-16L, T27 = 0x1.b0f72d33eff7bfa2fbc1059d90b6p-18L, T29 = 0x1.5ef2daf21d1113df38d0fbc00267p-19L, T31 = 0x1.1c77d6eac0234988cdaa04c96626p-20L, T33 = 0x1.cd2a5a292b180e0bdd701057dfe3p-22L, T35 = 0x1.75c7357d0298c01a31d0a6f7d518p-23L, T37 = 0x1.2f3190f4718a9a520f98f50081fcp-24L, pio4 = 0x1.921fb54442d18469898cc51701b8p-1L, pio4lo = 0x1.cd129024e088a67cc74020bbea60p-116L; static const double T39 = 0.000000028443389121318352, /* 0x1e8a7592977938.0p-78 */ T41 = 0.000000011981013102001973, /* 0x19baa1b1223219.0p-79 */ T43 = 0.0000000038303578044958070, /* 0x107385dfb24529.0p-80 */ T45 = 0.0000000034664378216909893, /* 0x1dc6c702a05262.0p-81 */ T47 = -0.0000000015090641701997785, /* -0x19ecef3569ebb6.0p-82 */ T49 = 0.0000000029449552300483952, /* 0x194c0668da786a.0p-81 */ T51 = -0.0000000022006995706097711, /* -0x12e763b8845268.0p-81 */ T53 = 0.0000000015468200913196612, /* 0x1a92fc98c29554.0p-82 */ T55 = -0.00000000061311613386849674, /* -0x151106cbc779a9.0p-83 */ T57 = 1.4912469681508012e-10; /* 0x147edbdba6f43a.0p-85 */ long double __kernel_tanl(long double x, long double y, int iy) { long double z, r, v, w, s; long double osign; int i; iy = (iy == 1 ? -1 : 1); /* XXX recover original interface */ osign = (x >= 0 ? 1.0 : -1.0); /* XXX slow, probably wrong for -0 */ if (fabsl(x) >= 0.67434) { if (x < 0) { x = -x; y = -y; } z = pio4 - x; w = pio4lo - y; x = z + w; y = 0.0; i = 1; } else i = 0; z = x * x; w = z * z; r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 + w * (T25 + w * (T29 + w * (T33 + w * (T37 + w * (T41 + w * (T45 + w * (T49 + w * (T53 + w * T57)))))))))))); v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 + w * (T27 + w * (T31 + w * (T35 + w * (T39 + w * (T43 + w * (T47 + w * (T51 + w * T55)))))))))))); s = z * x; r = y + z * (s * (r + v) + y); r += T3 * s; w = x + r; if (i == 1) { v = (long double) iy; return osign * (v - 2.0 * (x - (w * w / (w + v) - r))); } if (iy == 1) return w; else { /* * if allow error up to 2 ulp, simply return * -1.0 / (x+r) here */ /* compute -1.0 / (x+r) accurately */ long double a, t; z = w; z = z + 0x1p32 - 0x1p32; v = r - (z - x); /* z+v = r+x */ t = a = -1.0 / w; /* a = -1.0/w */ t = t + 0x1p32 - 0x1p32; s = 1.0 + t * z; return t + a * (s + t * v); } } diff --git a/lib/msun/ld128/s_cexpl.c b/lib/msun/ld128/s_cexpl.c index 1e4141f162c5..9e3eebfa750e 100644 --- a/lib/msun/ld128/s_cexpl.c +++ b/lib/msun/ld128/s_cexpl.c @@ -1,92 +1,91 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "fpmath.h" #include "math_private.h" #include "k_expl.h" /* XXX cexpl() should be converted to use bits likeo src/s_cexp.c. */ static const long double cexp_ovfl = 2.27892930024498818830197576893019292e+04L, exp_ovfl = 1.13565234062941439494919310779707649e+04L; long double complex cexpl(long double complex z) { long double c, exp_x, s, x, y; x = creall(z); y = cimagl(z); /* cexp(x + I 0) = exp(x) + I 0 */ if (y == 0) return (CMPLXL(expl(x), y)); /* cexp(0 + I y) = cos(y) + I sin(y) */ if (x == 0) { sincosl(y, &s, &c); return (CMPLXL(c, s)); } if (!isfinite(y)) { if (isfinite(x) || isnan(x)) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ return (CMPLXL(y - y, y - y)); } else if (isinf(x) && copysignl(1.L, x) < 0) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ return (CMPLXL(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ return (CMPLXL(x, y - y)); } } if (x > exp_ovfl && x < cexp_ovfl) { /* * x is between exp_ovfl and cexp_ovfl, so we must scale to * avoid overflow in exp(x). */ return (__ldexp_cexpl(z, 0)); } else { /* * Cases covered here: * - x < exp_ovfl and exp(x) won't overflow (common case) * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 * - x = +-Inf (generated by exp()) * - x = NaN (spurious inexact exception from y) */ exp_x = expl(x); sincosl(y, &s, &c); return (CMPLXL(exp_x * c, exp_x * s)); } } diff --git a/lib/msun/ld128/s_erfl.c b/lib/msun/ld128/s_erfl.c index 43ba2f0bed8b..1cc2dd04df23 100644 --- a/lib/msun/ld128/s_erfl.c +++ b/lib/msun/ld128/s_erfl.c @@ -1,327 +1,326 @@ /* @(#)s_erf.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See s_erf.c for complete comments. * * Converted to long double by Steven G. Kargl. */ #include #include "fpmath.h" #include "math.h" #include "math_private.h" /* XXX Prevent compilers from erroneously constant folding these: */ static const volatile long double tiny = 0x1p-10000L; static const double half= 0.5, one = 1, two = 2; /* * In the domain [0, 2**-40], only the first term in the power series * expansion of erf(x) is used. The magnitude of the first neglected * terms is less than 2**-120. */ static const long double efx = 1.28379167095512573896158903121545167e-01L, /* 0xecbff6a7, 0x481dd788, 0xb64d21a8, 0xeb06fc3f */ efx8 = 1.02703333676410059116927122497236133e+00L, /* 0xecbff6a7, 0x481dd788, 0xb64d21a8, 0xeb06ff3f */ /* * Domain [0, 0.84375], range ~[-1.919e-38, 1.919e-38]: * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-125.29 */ pp0 = 1.28379167095512573896158903121545167e-01L, /* 0x3ffc06eb, 0xa8214db6, 0x88d71d48, 0xa7f6bfec */ pp1 = -3.14931554396568573802046931159683404e-01L, /* 0xbffd427d, 0x6ada7263, 0x547eb096, 0x95f37463 */ pp2 = -5.27514920282183487103576956956725309e-02L, /* 0xbffab023, 0xe5a271e3, 0xb0e79b01, 0x2f7ac962 */ pp3 = -1.13202828509005281355609495523452713e-02L, /* 0xbff872f1, 0x6a5023a1, 0xe08b3884, 0x326af20f */ pp4 = -9.18626155872522453865998391206048506e-04L, /* 0xbff4e19f, 0xea5fb024, 0x43247a37, 0xe430b06c */ pp5 = -7.87518862406176274922506447157284230e-05L, /* 0xbff14a4f, 0x31a85fe0, 0x7fff2204, 0x09c49b37 */ pp6 = -3.42357944472240436548115331090560881e-06L, /* 0xbfeccb81, 0x4b43c336, 0xcd2eb6c2, 0x903f2d87 */ pp7 = -1.37317432573890412634717890726745428e-07L, /* 0xbfe826e3, 0x0e915eb6, 0x42aee414, 0xf7e36805 */ pp8 = -2.71115170113861755855049008732113726e-09L, /* 0xbfe2749e, 0x2b94fd00, 0xecb4d166, 0x0efb91f8 */ pp9 = -3.37925756196555959454018189718117864e-11L, /* 0xbfdc293e, 0x1d9060cb, 0xd043204a, 0x314cd7f0 */ qq1 = 4.76672625471551170489978555182449450e-01L, /* 0x3ffde81c, 0xde6531f0, 0x76803bee, 0x526e29e9 */ qq2 = 1.06713144672281502058807525850732240e-01L, /* 0x3ffbb518, 0xd7a6bb74, 0xcd9bdd33, 0x7601eee5 */ qq3 = 1.47747613127513761102189201923147490e-02L, /* 0x3ff8e423, 0xae527e18, 0xf12cb447, 0x723b4749 */ qq4 = 1.39939377672028671891148770908874816e-03L, /* 0x3ff56ed7, 0xba055d84, 0xc21b45c4, 0x388d1812 */ qq5 = 9.44302939359455241271983309378738276e-05L, /* 0x3ff18c11, 0xc18c99a4, 0x86d0fe09, 0x46387b4c */ qq6 = 4.56199342312522842161301671745365650e-06L, /* 0x3fed3226, 0x73421d05, 0x08875300, 0x32fa1432 */ qq7 = 1.53019260483764773845294600092361197e-07L, /* 0x3fe8489b, 0x3a63f627, 0x2b9ad2ce, 0x26516e57 */ qq8 = 3.25542691121324805094777901250005508e-09L, /* 0x3fe2bf6c, 0x26d93a29, 0x9142be7c, 0x9f1dd043 */ qq9 = 3.37405581964478060434410167262684979e-11L; /* 0x3fdc28c8, 0xfb8fa1be, 0x10e57eec, 0xaa19e49f */ static const long double erx = 8.42700792949714894142232424201210961e-01L, /* 0x3ffeaf76, 0x7a741088, 0xb0000000, 0x00000000 */ /* * Domain [0.84375, 1.25], range ~[-2.521e-36, 2.523e-36]: * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-120.15 */ pa0 = -2.48010117891186017024438233323795897e-17L, /* 0xbfc7c97f, 0x77812279, 0x6c877f22, 0xef4bfb2e */ pa1 = 4.15107497420594680894327969504526489e-01L, /* 0x3ffda911, 0xf096fbc2, 0x55662005, 0x2337fa64 */ pa2 = -3.94180628087084846724448515851892609e-02L, /* 0xbffa42e9, 0xab54528c, 0xad529da1, 0x6efc2af3 */ pa3 = 4.48897599625192107295954790681677462e-02L, /* 0x3ffa6fbc, 0xa65edba1, 0x0e4cbcea, 0x73ef9a31 */ pa4 = 8.02069252143016600110972019232995528e-02L, /* 0x3ffb4887, 0x0e8b548e, 0x3230b417, 0x11b553b3 */ pa5 = -1.02729816533435279443621120242391295e-02L, /* 0xbff850a0, 0x041de3ee, 0xd5bca6c9, 0x4ef5f9f2 */ pa6 = 5.70777694530755634864821094419982095e-03L, /* 0x3ff77610, 0x9b501e10, 0x4c978382, 0x742df68f */ pa7 = 1.22635150233075521018231779267077071e-03L, /* 0x3ff5417b, 0x0e623682, 0x60327da0, 0x96b9219e */ pa8 = 5.36100234820204569428412542856666503e-04L, /* 0x3ff41912, 0x27ceb4c1, 0x1d3298ec, 0x84ced627 */ pa9 = -1.97753571846365167177187858667583165e-04L, /* 0xbff29eb8, 0x23f5bcf3, 0x15c83c46, 0xe4fda98b */ pa10 = 6.19333039900846970674794789568415105e-05L, /* 0x3ff103c4, 0x60f88e46, 0xc0c9fb02, 0x13cc7fc1 */ pa11 = -5.40531400436645861492290270311751349e-06L, /* 0xbfed6abe, 0x9665f8a8, 0xdd0ad3ba, 0xe5dc0ee3 */ qa1 = 9.05041313265490487793231810291907851e-01L, /* 0x3ffecf61, 0x93340222, 0xe9930620, 0xc4e61168 */ qa2 = 6.79848064708886864767240880834868092e-01L, /* 0x3ffe5c15, 0x0ba858dc, 0xf7900ae9, 0xfea1e09a */ qa3 = 4.04720609926471677581066689316516445e-01L, /* 0x3ffd9e6f, 0x145e9b00, 0x6d8c1749, 0xd2928623 */ qa4 = 1.69183273898369996364661075664302225e-01L, /* 0x3ffc5a7c, 0xc2a363c1, 0xd6c19097, 0xef9b4063 */ qa5 = 7.44476185988067992342479750486764248e-02L, /* 0x3ffb30ef, 0xfc7259ef, 0x1bcbb089, 0x686dd62d */ qa6 = 2.02981172725892407200420389604788573e-02L, /* 0x3ff94c90, 0x7976cb0e, 0x21e1d36b, 0x0f09ca2b */ qa7 = 6.94281866271607668268269403102277234e-03L, /* 0x3ff7c701, 0x2b193250, 0xc5d46ecc, 0x374843d8 */ qa8 = 1.12952275469171559611651594706820034e-03L, /* 0x3ff52818, 0xfd2a7c06, 0xd13e38fd, 0xda4b34f5 */ qa9 = 3.13736683241992737197226578597710179e-04L, /* 0x3ff348fa, 0x0cb48d18, 0x051f849b, 0x135ccf74 */ qa10 = 1.17037675204033225470121134087771410e-05L, /* 0x3fee88b6, 0x98f47704, 0xa5d8f8f2, 0xc6422e11 */ qa11 = 4.61312518293853991439362806880973592e-06L, /* 0x3fed3594, 0xe31db94f, 0x3592b693, 0xed4386b4 */ qa12 = -1.02158572037456893687737553657431771e-06L; /* 0xbfeb123a, 0xd60d9b1e, 0x1f6fdeb9, 0x7dc8410a */ /* * Domain [1.25,2.85715], range ~[-2.922e-37,2.922e-37]: * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-121.36 */ static const long double ra0 = -9.86494292470069009555706994426014461e-03L, /* 0xbff84341, 0x239e8709, 0xe941b06a, 0xcb4b6ec5 */ ra1 = -1.13580436992565640457579040117568870e+00L, /* 0xbfff22c4, 0x133f7c0d, 0x72d5e231, 0x2eb1ee3f */ ra2 = -4.89744330295291950661185707066921755e+01L, /* 0xc00487cb, 0xa38b4fc2, 0xc136695b, 0xc1df8047 */ ra3 = -1.10766149300215937173768072715352140e+03L, /* 0xc00914ea, 0x55e6beb3, 0xabc50e07, 0xb6e5664d */ ra4 = -1.49991031232170934967642795601952100e+04L, /* 0xc00cd4b8, 0xd33243e6, 0xffbf6545, 0x3c57ef6e */ ra5 = -1.29805749738318462882524181556996692e+05L, /* 0xc00ffb0d, 0xbfeed9b6, 0x5b2a3ff4, 0xe245bd3c */ ra6 = -7.42828497044940065828871976644647850e+05L, /* 0xc0126ab5, 0x8fe7caca, 0x473352d9, 0xcd4e0c90 */ ra7 = -2.85637299581890734287995171242421106e+06L, /* 0xc0145cad, 0xa7f76fe7, 0x3e358051, 0x1799f927 */ ra8 = -7.40674797129824999383748865571026084e+06L, /* 0xc015c412, 0x6fe29c02, 0x298ad158, 0x7d24e45c */ ra9 = -1.28653420911930973914078724204151759e+07L, /* 0xc016889e, 0x7c2eb0dc, 0x95d5863b, 0x0aa34dc3 */ ra10 = -1.47198163599330179552932489109452638e+07L, /* 0xc016c136, 0x90b84923, 0xf9bcb497, 0x19bbd0f5 */ ra11 = -1.07812992258382800318665248311522624e+07L, /* 0xc0164904, 0xe673a113, 0x35d7f079, 0xe13701f3 */ ra12 = -4.83545565681708642630419905537756076e+06L, /* 0xc0152721, 0xfea094a8, 0x869eb39d, 0x413d6f13 */ ra13 = -1.23956521201673964822976917356685286e+06L, /* 0xc0132ea0, 0xd3646baa, 0x2fe62b0d, 0xbae5ce85 */ ra14 = -1.62289333553652417591275333240371812e+05L, /* 0xc0103cf8, 0xaab1e2d6, 0x4c25e014, 0x248d76ab */ ra15 = -8.82890392601176969729168894389833110e+03L, /* 0xc00c13e7, 0x3b3d8f94, 0x6fbda6f6, 0xe7049a82 */ ra16 = -1.22591866337261720023681535568334619e+02L, /* 0xc005ea5e, 0x12358891, 0xcfa712c5, 0x77f050d4 */ sa1 = 6.44508918884710829371852723353794047e+01L, /* 0x400501cd, 0xb69a6c0f, 0x5716de14, 0x47161af6 */ sa2 = 1.76118475473171481523704824327358534e+03L, /* 0x4009b84b, 0xd305829f, 0xc4c771b0, 0xbf1f7f9b */ sa3 = 2.69448346969488374857087646131950188e+04L, /* 0x400da503, 0x56bacc05, 0x4fdba68d, 0x2cca27e6 */ sa4 = 2.56826633369941456778326497384543763e+05L, /* 0x4010f59d, 0x51124428, 0x69c41de6, 0xbd0d5753 */ sa5 = 1.60647413092257206847700054645905859e+06L, /* 0x40138834, 0xa2184244, 0x557a1bed, 0x68c9d556 */ sa6 = 6.76963075165099718574753447122393797e+06L, /* 0x40159d2f, 0x7b01b0cc, 0x8bac9e95, 0x5d35d56e */ sa7 = 1.94295690905361884290986932493647741e+07L, /* 0x40172878, 0xc1172d61, 0x3068501e, 0x2f3c71da */ sa8 = 3.79774781017759149060839255547073541e+07L, /* 0x401821be, 0xc30d06fe, 0x410563d7, 0x032111fd */ sa9 = 5.00659831846029484248302236457727397e+07L, /* 0x40187df9, 0x1f97a111, 0xc51d6ac2, 0x4b389793 */ sa10 = 4.36486287620506484276130525941972541e+07L, /* 0x40184d03, 0x3a618ae0, 0x2a723357, 0xfa45c60a */ sa11 = 2.43779678791333894255510508253951934e+07L, /* 0x401773fa, 0x6fe10ee2, 0xc467850d, 0xc6b7ff30 */ sa12 = 8.30732360384443202039372372212966542e+06L, /* 0x4015fb09, 0xee6a5631, 0xdd98de7e, 0x8b00461a */ sa13 = 1.60160846942050515734192397495105693e+06L, /* 0x40138704, 0x8782bf13, 0x5b8fb315, 0xa898abe5 */ sa14 = 1.54255505242533291014555153757001825e+05L, /* 0x40102d47, 0xc0abc98e, 0x843c9490, 0xb4352440 */ sa15 = 5.87949220002375547561467275493888824e+03L, /* 0x400b6f77, 0xe00d21d1, 0xec4d41e8, 0x2f8e1673 */ sa16 = 4.97272976346793193860385983372237710e+01L; /* 0x40048dd1, 0x816c1b3f, 0x24f540a6, 0x4cfe03cc */ /* * Domain [2.85715,9], range ~[-7.886e-37,7.918e-37]: * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-120 */ static const long double rb0 = -9.86494292470008707171371994479162369e-3L, /* 0xbff84341, 0x239e86f4, 0x2f57e561, 0xf4469360 */ rb1 = -1.57047326624110727986326503729442830L, /* 0xbfff920a, 0x8935bf73, 0x8803b894, 0x4656482d */ rb2 = -1.03228196364885474342132255440317065e2L, /* 0xc0059ce9, 0xac4ed0ff, 0x2cff0ff7, 0x5e70d1ab */ rb3 = -3.74000570653418227179358710865224376e3L, /* 0xc00ad380, 0x2ebf7835, 0xf6b07ed2, 0x861242f7 */ rb4 = -8.35435477739098044190860390632813956e4L, /* 0xc00f4657, 0x8c3ae934, 0x3647d7b3, 0x80e76fb7 */ rb5 = -1.21398672055223642118716640216747152e6L, /* 0xc0132862, 0x2b8761c8, 0x27d18c0f, 0x137c9463 */ rb6 = -1.17669175877248796101665344873273970e7L, /* 0xc0166719, 0x0b2cea46, 0x81f14174, 0x11602ea5 */ rb7 = -7.66108006086998253606773064264599615e7L, /* 0xc019243f, 0x3c26f4f0, 0x1cc05241, 0x3b953728 */ rb8 = -3.32547117558141845968704725353130804e8L, /* 0xc01b3d24, 0x42d8ee26, 0x24ef6f3b, 0x604a8c65 */ rb9 = -9.41561252426350696802167711221739746e8L, /* 0xc01cc0f8, 0xad23692a, 0x8ddb2310, 0xe9937145 */ rb10 = -1.67157110805390944549427329626281063e9L, /* 0xc01d8e88, 0x9a903734, 0x09a55fa3, 0xd205c903 */ rb11 = -1.74339631004410841337645931421427373e9L, /* 0xc01d9fa8, 0x77582d2a, 0xc183b8ab, 0x7e00cb05 */ rb12 = -9.57655233596934915727573141357471703e8L, /* 0xc01cc8a5, 0x460cc685, 0xd0271fa0, 0x6a70e3da */ rb13 = -2.26320062731339353035254704082495066e8L, /* 0xc01aafab, 0xd7d76721, 0xc9720e11, 0x6a8bd489 */ rb14 = -1.42777302996263256686002973851837039e7L, /* 0xc016b3b8, 0xc499689f, 0x2b88d965, 0xc32414f9 */ sb1 = 1.08512869705594540211033733976348506e2L, /* 0x4005b20d, 0x2db7528d, 0x00d20dcb, 0x858f6191 */ sb2 = 5.02757713761390460534494530537572834e3L, /* 0x400b3a39, 0x3bf4a690, 0x3025d28d, 0xfd40a891 */ sb3 = 1.31019107205412870059331647078328430e5L, /* 0x400fffcb, 0x1b71d05e, 0x3b28361d, 0x2a3c3690 */ sb4 = 2.13021555152296846166736757455018030e6L, /* 0x40140409, 0x3c6984df, 0xc4491d7c, 0xb04aa08d */ sb5 = 2.26649105281820861953868568619768286e7L, /* 0x401759d6, 0xce8736f0, 0xf28ad037, 0x2a901e0c */ sb6 = 1.61071939490875921812318684143076081e8L, /* 0x401a3338, 0x686fb541, 0x6bd27d06, 0x4f95c9ac */ sb7 = 7.66895673844301852676056750497991966e8L, /* 0x401c6daf, 0x31cec121, 0x54699126, 0x4bd9bf9e */ sb8 = 2.41884450436101936436023058196042526e9L, /* 0x401e2059, 0x46b0b8d7, 0x87b64cbf, 0x78bc296d */ sb9 = 4.92403055884071695093305291535107666e9L, /* 0x401f257e, 0xbe5ed739, 0x39e17346, 0xcadd2e55 */ sb10 = 6.18627786365587486459633615573786416e9L, /* 0x401f70bb, 0x1be7a7e7, 0x6a45b5ae, 0x607c70f0 */ sb11 = 4.45898013426501378097430226324743199e9L, /* 0x401f09c6, 0xa32643d7, 0xf1724620, 0x9ea46c32 */ sb12 = 1.63006115763329848117160344854224975e9L, /* 0x401d84a3, 0x0996887f, 0x65a4f43b, 0x978c1d74 */ sb13 = 2.39216717012421697446304015847567721e8L, /* 0x401ac845, 0x09a065c2, 0x30095da7, 0x9d72d6ae */ sb14 = 7.84837329009278694937250358810225609e6L; /* 0x4015df06, 0xd5290e15, 0x63031fac, 0x4d9c894c */ /* * Domain [9,108], range ~[-5.324e-38,5.340e-38]: * |log(x*erfc(x)) + x**2 + 0.5625 - r(x)/s(x)| < 2**-124 */ static const long double rc0 = -9.86494292470008707171367567652935673e-3L, /* 0xbff84341, 0x239e86f4, 0x2f57e55b, 0x1aa10fd3 */ rc1 = -1.26229447747315096406518846411562266L, /* 0xbfff4325, 0xbb1aab28, 0xda395cd9, 0xfb861c15 */ rc2 = -6.13742634438922591780742637728666162e1L, /* 0xc004eafe, 0x7dd51cd8, 0x3c7c5928, 0x751e50cf */ rc3 = -1.50455835478908280402912854338421517e3L, /* 0xc0097823, 0xbc15b9ab, 0x3d60745c, 0x523e80a5 */ rc4 = -2.04415631865861549920184039902945685e4L, /* 0xc00d3f66, 0x40b3fc04, 0x5388f2ec, 0xb009e1f0 */ rc5 = -1.57625662981714582753490610560037638e5L, /* 0xc01033dc, 0xd4dc95b6, 0xfd4da93b, 0xf355b4a9 */ rc6 = -6.73473451616752528402917538033283794e5L, /* 0xc01248d8, 0x2e73a4f9, 0xcded49c5, 0xfa3bfeb7 */ rc7 = -1.47433165421387483167186683764364857e6L, /* 0xc01367f1, 0xba77a8f7, 0xcfdd0dbb, 0x25d554b3 */ rc8 = -1.38811981807868828563794929997744139e6L, /* 0xc01352e5, 0x7d16d9ad, 0xbbdcbf38, 0x38fbc5ea */ rc9 = -3.59659700530831825640766479698155060e5L, /* 0xc0115f3a, 0xecd57f45, 0x21f8ad6c, 0x910a5958 */ sc1 = 7.72730753022908298637508998072635696e1L, /* 0x40053517, 0xa10d52bc, 0xdabb55b6, 0xbd0328cd */ sc2 = 2.36825757341694050500333261769082182e3L, /* 0x400a2808, 0x3e0a9b42, 0x82977842, 0x9c5de29e */ sc3 = 3.72210540173034735352888847134073099e4L, /* 0x400e22ca, 0x1ba827ef, 0xac8390d7, 0x1fc39a41 */ sc4 = 3.24136032646418336712461033591393412e5L, /* 0x40113c8a, 0x0216e100, 0xc59d1e44, 0xf0e68d9d */ sc5 = 1.57836135851134393802505823370009175e6L, /* 0x40138157, 0x95bc7664, 0x17575961, 0xdbe58eeb */ sc6 = 4.12881981392063738026679089714182355e6L, /* 0x4014f801, 0x9e82e8d2, 0xb8b3a70e, 0xfd84185d */ sc7 = 5.24438427289213488410596395361544142e6L, /* 0x40154017, 0x81177109, 0x2aa6c3b0, 0x1f106625 */ sc8 = 2.59909544563616121735963429710382149e6L, /* 0x40143d45, 0xbb90a9b1, 0x12bf9390, 0xa827a700 */ sc9 = 2.80930665169282501639651995082335693e5L; /* 0x40111258, 0xaa92222e, 0xa97e3216, 0xa237fa6c */ long double erfl(long double x) { long double ax,R,S,P,Q,s,y,z,r; uint64_t lx, llx; int32_t i; uint16_t hx; EXTRACT_LDBL128_WORDS(hx, lx, llx, x); if((hx & 0x7fff) == 0x7fff) { /* erfl(nan)=nan */ i = (hx>>15)<<1; return (1-i)+one/x; /* erfl(+-inf)=+-1 */ } ax = fabsl(x); if(ax < 0.84375) { if(ax < 0x1p-40L) { if(ax < 0x1p-16373L) return (8*x+efx8*x)/8; /* avoid spurious underflow */ return x + efx*x; } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*(pp5+z*(pp6+z*(pp7+ z*(pp8+z*pp9)))))))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*(qq6+z*(qq7+ z*(qq8+z*qq9)))))))); y = r/s; return x + x*y; } if(ax < 1.25) { s = ax-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*(pa7+ s*(pa8+s*(pa9+s*(pa10+s*pa11)))))))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*(qa7+ s*(qa8+s*(qa9+s*(qa10+s*(qa11+s*qa12))))))))))); if(x>=0) return (erx + P/Q); else return (-erx - P/Q); } if (ax >= 9) { /* inf>|x|>= 9 */ if(x>=0) return (one-tiny); else return (tiny-one); } s = one/(ax*ax); if(ax < 2.85715) { /* |x| < 2.85715 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+ s*(ra8+s*(ra9+s*(ra10+s*(ra11+s*(ra12+s*(ra13+s*(ra14+ s*(ra15+s*ra16))))))))))))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*(sa8+s*(sa9+s*(sa10+s*(sa11+s*(sa12+s*(sa13+s*(sa14+ s*(sa15+s*sa16))))))))))))))); } else { /* |x| >= 2.85715 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*(rb7+ s*(rb8+s*(rb9+s*(rb10+s*(rb11+s*(rb12+s*(rb13+ s*rb14))))))))))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*(sb7+ s*(sb8+s*(sb9+s*(sb10+s*(sb11+s*(sb12+s*(sb13+ s*sb14))))))))))))); } z = (float)ax; r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S); if(x>=0) return (one-r/ax); else return (r/ax-one); } long double erfcl(long double x) { long double ax,R,S,P,Q,s,y,z,r; uint64_t lx, llx; uint16_t hx; EXTRACT_LDBL128_WORDS(hx, lx, llx, x); if((hx & 0x7fff) == 0x7fff) { /* erfcl(nan)=nan */ /* erfcl(+-inf)=0,2 */ return ((hx>>15)<<1)+one/x; } ax = fabsl(x); if(ax < 0.84375L) { if(ax < 0x1p-34L) return one-x; z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*(pp5+z*(pp6+z*(pp7+ z*(pp8+z*pp9)))))))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*(qq6+z*(qq7+ z*(qq8+z*qq9)))))))); y = r/s; if(ax < 0.25L) { /* x<1/4 */ return one-(x+x*y); } else { r = x*y; r += (x-half); return half - r; } } if(ax < 1.25L) { s = ax-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*(pa7+ s*(pa8+s*(pa9+s*(pa10+s*pa11)))))))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*(qa7+ s*(qa8+s*(qa9+s*(qa10+s*(qa11+s*qa12))))))))))); if(x>=0) { z = one-erx; return z - P/Q; } else { z = erx+P/Q; return one+z; } } if(ax < 108) { /* |x| < 108 */ s = one/(ax*ax); if(ax < 2.85715) { /* |x| < 2.85715 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+ s*(ra8+s*(ra9+s*(ra10+s*(ra11+s*(ra12+s*(ra13+s*(ra14+ s*(ra15+s*ra16))))))))))))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*(sa8+s*(sa9+s*(sa10+s*(sa11+s*(sa12+s*(sa13+s*(sa14+ s*(sa15+s*sa16))))))))))))))); } else if(ax < 9) { R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*(rb7+ s*(rb8+s*(rb9+s*(rb10+s*(rb11+s*(rb12+s*(rb13+ s*rb14))))))))))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*(sb7+ s*(sb8+s*(sb9+s*(sb10+s*(sb11+s*(sb12+s*(sb13+ s*sb14))))))))))))); } else { if(x < -9) return two-tiny; /* x < -9 */ R=rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+s*(rc6+s*(rc7+ s*(rc8+s*rc9)))))))); S=one+s*(sc1+s*(sc2+s*(sc3+s*(sc4+s*(sc5+s*(sc6+s*(sc7+ s*(sc8+s*sc9)))))))); } z = (float)ax; r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S); if(x>0) return r/ax; else return two-r/ax; } else { if(x>0) return tiny*tiny; else return two-tiny; } } diff --git a/lib/msun/ld128/s_exp2l.c b/lib/msun/ld128/s_exp2l.c index 74ae8c2daad8..249cb4cb8bb0 100644 --- a/lib/msun/ld128/s_exp2l.c +++ b/lib/msun/ld128/s_exp2l.c @@ -1,427 +1,426 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #include "math.h" #define TBLBITS 7 #define TBLSIZE (1 << TBLBITS) #define BIAS (LDBL_MAX_EXP - 1) #define EXPMASK (BIAS + LDBL_MAX_EXP) static volatile long double huge = 0x1p10000L, twom10000 = 0x1p-10000L; static const long double P1 = 0x1.62e42fefa39ef35793c7673007e6p-1L, P2 = 0x1.ebfbdff82c58ea86f16b06ec9736p-3L, P3 = 0x1.c6b08d704a0bf8b33a762bad3459p-5L, P4 = 0x1.3b2ab6fba4e7729ccbbe0b4f3fc2p-7L, P5 = 0x1.5d87fe78a67311071dee13fd11d9p-10L, P6 = 0x1.430912f86c7876f4b663b23c5fe5p-13L; static const double P7 = 0x1.ffcbfc588b041p-17, P8 = 0x1.62c0223a5c7c7p-20, P9 = 0x1.b52541ff59713p-24, P10 = 0x1.e4cf56a391e22p-28, redux = 0x1.8p112 / TBLSIZE; static const long double tbl[TBLSIZE] = { 0x1.6a09e667f3bcc908b2fb1366dfeap-1L, 0x1.6c012750bdabeed76a99800f4edep-1L, 0x1.6dfb23c651a2ef220e2cbe1bc0d4p-1L, 0x1.6ff7df9519483cf87e1b4f3e1e98p-1L, 0x1.71f75e8ec5f73dd2370f2ef0b148p-1L, 0x1.73f9a48a58173bd5c9a4e68ab074p-1L, 0x1.75feb564267c8bf6e9aa33a489a8p-1L, 0x1.780694fde5d3f619ae02808592a4p-1L, 0x1.7a11473eb0186d7d51023f6ccb1ap-1L, 0x1.7c1ed0130c1327c49334459378dep-1L, 0x1.7e2f336cf4e62105d02ba1579756p-1L, 0x1.80427543e1a11b60de67649a3842p-1L, 0x1.82589994cce128acf88afab34928p-1L, 0x1.8471a4623c7acce52f6b97c6444cp-1L, 0x1.868d99b4492ec80e41d90ac2556ap-1L, 0x1.88ac7d98a669966530bcdf2d4cc0p-1L, 0x1.8ace5422aa0db5ba7c55a192c648p-1L, 0x1.8cf3216b5448bef2aa1cd161c57ap-1L, 0x1.8f1ae991577362b982745c72eddap-1L, 0x1.9145b0b91ffc588a61b469f6b6a0p-1L, 0x1.93737b0cdc5e4f4501c3f2540ae8p-1L, 0x1.95a44cbc8520ee9b483695a0e7fep-1L, 0x1.97d829fde4e4f8b9e920f91e8eb6p-1L, 0x1.9a0f170ca07b9ba3109b8c467844p-1L, 0x1.9c49182a3f0901c7c46b071f28dep-1L, 0x1.9e86319e323231824ca78e64c462p-1L, 0x1.a0c667b5de564b29ada8b8cabbacp-1L, 0x1.a309bec4a2d3358c171f770db1f4p-1L, 0x1.a5503b23e255c8b424491caf88ccp-1L, 0x1.a799e1330b3586f2dfb2b158f31ep-1L, 0x1.a9e6b5579fdbf43eb243bdff53a2p-1L, 0x1.ac36bbfd3f379c0db966a3126988p-1L, 0x1.ae89f995ad3ad5e8734d17731c80p-1L, 0x1.b0e07298db66590842acdfc6fb4ep-1L, 0x1.b33a2b84f15faf6bfd0e7bd941b0p-1L, 0x1.b59728de559398e3881111648738p-1L, 0x1.b7f76f2fb5e46eaa7b081ab53ff6p-1L, 0x1.ba5b030a10649840cb3c6af5b74cp-1L, 0x1.bcc1e904bc1d2247ba0f45b3d06cp-1L, 0x1.bf2c25bd71e088408d7025190cd0p-1L, 0x1.c199bdd85529c2220cb12a0916bap-1L, 0x1.c40ab5fffd07a6d14df820f17deap-1L, 0x1.c67f12e57d14b4a2137fd20f2a26p-1L, 0x1.c8f6d9406e7b511acbc48805c3f6p-1L, 0x1.cb720dcef90691503cbd1e949d0ap-1L, 0x1.cdf0b555dc3f9c44f8958fac4f12p-1L, 0x1.d072d4a07897b8d0f22f21a13792p-1L, 0x1.d2f87080d89f18ade123989ea50ep-1L, 0x1.d5818dcfba48725da05aeb66dff8p-1L, 0x1.d80e316c98397bb84f9d048807a0p-1L, 0x1.da9e603db3285708c01a5b6d480cp-1L, 0x1.dd321f301b4604b695de3c0630c0p-1L, 0x1.dfc97337b9b5eb968cac39ed284cp-1L, 0x1.e264614f5a128a12761fa17adc74p-1L, 0x1.e502ee78b3ff6273d130153992d0p-1L, 0x1.e7a51fbc74c834b548b2832378a4p-1L, 0x1.ea4afa2a490d9858f73a18f5dab4p-1L, 0x1.ecf482d8e67f08db0312fb949d50p-1L, 0x1.efa1bee615a27771fd21a92dabb6p-1L, 0x1.f252b376bba974e8696fc3638f24p-1L, 0x1.f50765b6e4540674f84b762861a6p-1L, 0x1.f7bfdad9cbe138913b4bfe72bd78p-1L, 0x1.fa7c1819e90d82e90a7e74b26360p-1L, 0x1.fd3c22b8f71f10975ba4b32bd006p-1L, 0x1.0000000000000000000000000000p+0L, 0x1.0163da9fb33356d84a66ae336e98p+0L, 0x1.02c9a3e778060ee6f7caca4f7a18p+0L, 0x1.04315e86e7f84bd738f9a20da442p+0L, 0x1.059b0d31585743ae7c548eb68c6ap+0L, 0x1.0706b29ddf6ddc6dc403a9d87b1ep+0L, 0x1.0874518759bc808c35f25d942856p+0L, 0x1.09e3ecac6f3834521e060c584d5cp+0L, 0x1.0b5586cf9890f6298b92b7184200p+0L, 0x1.0cc922b7247f7407b705b893dbdep+0L, 0x1.0e3ec32d3d1a2020742e4f8af794p+0L, 0x1.0fb66affed31af232091dd8a169ep+0L, 0x1.11301d0125b50a4ebbf1aed9321cp+0L, 0x1.12abdc06c31cbfb92bad324d6f84p+0L, 0x1.1429aaea92ddfb34101943b2588ep+0L, 0x1.15a98c8a58e512480d573dd562aep+0L, 0x1.172b83c7d517adcdf7c8c50eb162p+0L, 0x1.18af9388c8de9bbbf70b9a3c269cp+0L, 0x1.1a35beb6fcb753cb698f692d2038p+0L, 0x1.1bbe084045cd39ab1e72b442810ep+0L, 0x1.1d4873168b9aa7805b8028990be8p+0L, 0x1.1ed5022fcd91cb8819ff61121fbep+0L, 0x1.2063b88628cd63b8eeb0295093f6p+0L, 0x1.21f49917ddc962552fd29294bc20p+0L, 0x1.2387a6e75623866c1fadb1c159c0p+0L, 0x1.251ce4fb2a63f3582ab7de9e9562p+0L, 0x1.26b4565e27cdd257a673281d3068p+0L, 0x1.284dfe1f5638096cf15cf03c9fa0p+0L, 0x1.29e9df51fdee12c25d15f5a25022p+0L, 0x1.2b87fd0dad98ffddea46538fca24p+0L, 0x1.2d285a6e4030b40091d536d0733ep+0L, 0x1.2ecafa93e2f5611ca0f45d5239a4p+0L, 0x1.306fe0a31b7152de8d5a463063bep+0L, 0x1.32170fc4cd8313539cf1c3009330p+0L, 0x1.33c08b26416ff4c9c8610d96680ep+0L, 0x1.356c55f929ff0c94623476373be4p+0L, 0x1.371a7373aa9caa7145502f45452ap+0L, 0x1.38cae6d05d86585a9cb0d9bed530p+0L, 0x1.3a7db34e59ff6ea1bc9299e0a1fep+0L, 0x1.3c32dc313a8e484001f228b58cf0p+0L, 0x1.3dea64c12342235b41223e13d7eep+0L, 0x1.3fa4504ac801ba0bf701aa417b9cp+0L, 0x1.4160a21f72e29f84325b8f3dbacap+0L, 0x1.431f5d950a896dc704439410b628p+0L, 0x1.44e086061892d03136f409df0724p+0L, 0x1.46a41ed1d005772512f459229f0ap+0L, 0x1.486a2b5c13cd013c1a3b69062f26p+0L, 0x1.4a32af0d7d3de672d8bcf46f99b4p+0L, 0x1.4bfdad5362a271d4397afec42e36p+0L, 0x1.4dcb299fddd0d63b36ef1a9e19dep+0L, 0x1.4f9b2769d2ca6ad33d8b69aa0b8cp+0L, 0x1.516daa2cf6641c112f52c84d6066p+0L, 0x1.5342b569d4f81df0a83c49d86bf4p+0L, 0x1.551a4ca5d920ec52ec620243540cp+0L, 0x1.56f4736b527da66ecb004764e61ep+0L, 0x1.58d12d497c7fd252bc2b7343d554p+0L, 0x1.5ab07dd48542958c93015191e9a8p+0L, 0x1.5c9268a5946b701c4b1b81697ed4p+0L, 0x1.5e76f15ad21486e9be4c20399d12p+0L, 0x1.605e1b976dc08b076f592a487066p+0L, 0x1.6247eb03a5584b1f0fa06fd2d9eap+0L, 0x1.6434634ccc31fc76f8714c4ee122p+0L, 0x1.66238825522249127d9e29b92ea2p+0L, 0x1.68155d44ca973081c57227b9f69ep+0L, }; static const float eps[TBLSIZE] = { -0x1.5c50p-101, -0x1.5d00p-106, 0x1.8e90p-102, -0x1.5340p-103, 0x1.1bd0p-102, -0x1.4600p-105, -0x1.7a40p-104, 0x1.d590p-102, -0x1.d590p-101, 0x1.b100p-103, -0x1.0d80p-105, 0x1.6b00p-103, -0x1.9f00p-105, 0x1.c400p-103, 0x1.e120p-103, -0x1.c100p-104, -0x1.9d20p-103, 0x1.a800p-108, 0x1.4c00p-106, -0x1.9500p-106, 0x1.6900p-105, -0x1.29d0p-100, 0x1.4c60p-103, 0x1.13a0p-102, -0x1.5b60p-103, -0x1.1c40p-103, 0x1.db80p-102, 0x1.91a0p-102, 0x1.dc00p-105, 0x1.44c0p-104, 0x1.9710p-102, 0x1.8760p-103, -0x1.a720p-103, 0x1.ed20p-103, -0x1.49c0p-102, -0x1.e000p-111, 0x1.86a0p-103, 0x1.2b40p-103, -0x1.b400p-108, 0x1.1280p-99, -0x1.02d8p-102, -0x1.e3d0p-103, -0x1.b080p-105, -0x1.f100p-107, -0x1.16c0p-105, -0x1.1190p-103, -0x1.a7d2p-100, 0x1.3450p-103, -0x1.67c0p-105, 0x1.4b80p-104, -0x1.c4e0p-103, 0x1.6000p-108, -0x1.3f60p-105, 0x1.93f0p-104, 0x1.5fe0p-105, 0x1.6f80p-107, -0x1.7600p-106, 0x1.21e0p-106, -0x1.3a40p-106, -0x1.40c0p-104, -0x1.9860p-105, -0x1.5d40p-108, -0x1.1d70p-106, 0x1.2760p-105, 0x0.0000p+0, 0x1.21e2p-104, -0x1.9520p-108, -0x1.5720p-106, -0x1.4810p-106, -0x1.be00p-109, 0x1.0080p-105, -0x1.5780p-108, -0x1.d460p-105, -0x1.6140p-105, 0x1.4630p-104, 0x1.ad50p-103, 0x1.82e0p-105, 0x1.1d3cp-101, 0x1.6100p-107, 0x1.ec30p-104, 0x1.f200p-108, 0x1.0b40p-103, 0x1.3660p-102, 0x1.d9d0p-103, -0x1.02d0p-102, 0x1.b070p-103, 0x1.b9c0p-104, -0x1.01c0p-103, -0x1.dfe0p-103, 0x1.1b60p-104, -0x1.ae94p-101, -0x1.3340p-104, 0x1.b3d8p-102, -0x1.6e40p-105, -0x1.3670p-103, 0x1.c140p-104, 0x1.1840p-101, 0x1.1ab0p-102, -0x1.a400p-104, 0x1.1f00p-104, -0x1.7180p-103, 0x1.4ce0p-102, 0x1.9200p-107, -0x1.54c0p-103, 0x1.1b80p-105, -0x1.1828p-101, 0x1.5720p-102, -0x1.a060p-100, 0x1.9160p-102, 0x1.a280p-104, 0x1.3400p-107, 0x1.2b20p-102, 0x1.7800p-108, 0x1.cfd0p-101, 0x1.2ef0p-102, -0x1.2760p-99, 0x1.b380p-104, 0x1.0048p-101, -0x1.60b0p-102, 0x1.a1ccp-100, -0x1.a640p-104, -0x1.08a0p-101, 0x1.7e60p-102, 0x1.22c0p-103, -0x1.7200p-106, 0x1.f0f0p-102, 0x1.eb4ep-99, 0x1.c6e0p-103, }; /* * exp2l(x): compute the base 2 exponential of x * * Accuracy: Peak error < 0.502 ulp. * * Method: (accurate tables) * * Reduce x: * x = 2**k + y, for integer k and |y| <= 1/2. * Thus we have exp2(x) = 2**k * exp2(y). * * Reduce y: * y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE. * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]), * with |z - eps[i]| <= 2**-8 + 2**-98 for the table used. * * We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via * a degree-10 minimax polynomial with maximum error under 2**-120. * The values in exp2t[] and eps[] are chosen such that * exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such * that exp2t[i] is accurate to 2**-122. * * Note that the range of i is +-TBLSIZE/2, so we actually index the tables * by i0 = i + TBLSIZE/2. * * This method is due to Gal, with many details due to Gal and Bachelis: * * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991). */ long double exp2l(long double x) { union IEEEl2bits u, v; long double r, t, twopk, twopkp10000, z; uint32_t hx, ix, i0; int k; u.e = x; /* Filter out exceptional cases. */ hx = u.xbits.expsign; ix = hx & EXPMASK; if (ix >= BIAS + 14) { /* |x| >= 16384 */ if (ix == BIAS + LDBL_MAX_EXP) { if (u.xbits.manh != 0 || u.xbits.manl != 0 || (hx & 0x8000) == 0) return (x + x); /* x is NaN or +Inf */ else return (0.0); /* x is -Inf */ } if (x >= 16384) return (huge * huge); /* overflow */ if (x <= -16495) return (twom10000 * twom10000); /* underflow */ } else if (ix <= BIAS - 115) { /* |x| < 0x1p-115 */ return (1.0 + x); } /* * Reduce x, computing z, i0, and k. The low bits of x + redux * contain the 16-bit integer part of the exponent (k) followed by * TBLBITS fractional bits (i0). We use bit tricks to extract these * as integers, then set z to the remainder. * * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8. * Then the low-order word of x + redux is 0x000abc12, * We split this into k = 0xabc and i0 = 0x12 (adjusted to * index into the table), then we compute z = 0x0.003456p0. * * XXX If the exponent is negative, the computation of k depends on * '>>' doing sign extension. */ u.e = x + redux; i0 = (u.bits.manl & 0xffffffff) + TBLSIZE / 2; k = (int)i0 >> TBLBITS; i0 = i0 & (TBLSIZE - 1); u.e -= redux; z = x - u.e; v.xbits.manh = 0; v.xbits.manl = 0; if (k >= LDBL_MIN_EXP) { v.xbits.expsign = LDBL_MAX_EXP - 1 + k; twopk = v.e; } else { v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000; twopkp10000 = v.e; } /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ t = tbl[i0]; /* exp2t[i0] */ z -= eps[i0]; /* eps[i0] */ r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * (P5 + z * (P6 + z * (P7 + z * (P8 + z * (P9 + z * P10))))))))); /* Scale by 2**k. */ if(k >= LDBL_MIN_EXP) { if (k == LDBL_MAX_EXP) return (r * 2.0 * 0x1p16383L); return (r * twopk); } else { return (r * twopkp10000 * twom10000); } } diff --git a/lib/msun/ld128/s_expl.c b/lib/msun/ld128/s_expl.c index 6d6c22d917fe..e1358e2213a0 100644 --- a/lib/msun/ld128/s_expl.c +++ b/lib/msun/ld128/s_expl.c @@ -1,320 +1,319 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009-2013 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Optimized by Bruce D. Evans. */ -#include /* * ld128 version of s_expl.c. See ../ld80/s_expl.c for most comments. */ #include #include "fpmath.h" #include "math.h" #include "math_private.h" #include "k_expl.h" /* XXX Prevent compilers from erroneously constant folding these: */ static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L; static const long double twom10000 = 0x1p-10000L; static const long double /* log(2**16384 - 0.5) rounded towards zero: */ /* log(2**16384 - 0.5 + 1) rounded towards zero for expm1l() is the same: */ o_threshold = 11356.523406294143949491931077970763428L, /* log(2**(-16381-64-1)) rounded towards zero: */ u_threshold = -11433.462743336297878837243843452621503L; long double expl(long double x) { union IEEEl2bits u; long double hi, lo, t, twopk; int k; uint16_t hx, ix; /* Filter out exceptional cases. */ u.e = x; hx = u.xbits.expsign; ix = hx & 0x7fff; if (ix >= BIAS + 13) { /* |x| >= 8192 or x is NaN */ if (ix == BIAS + LDBL_MAX_EXP) { if (hx & 0x8000) /* x is -Inf or -NaN */ RETURNF(-1 / x); RETURNF(x + x); /* x is +Inf or +NaN */ } if (x > o_threshold) RETURNF(huge * huge); if (x < u_threshold) RETURNF(tiny * tiny); } else if (ix < BIAS - 114) { /* |x| < 0x1p-114 */ RETURNF(1 + x); /* 1 with inexact iff x != 0 */ } ENTERI(); twopk = 1; __k_expl(x, &hi, &lo, &k); t = SUM2P(hi, lo); /* Scale by 2**k. */ /* * XXX sparc64 multiplication was so slow that scalbnl() is faster, * but performance on aarch64 and riscv hasn't yet been quantified. */ if (k >= LDBL_MIN_EXP) { if (k == LDBL_MAX_EXP) RETURNI(t * 2 * 0x1p16383L); SET_LDBL_EXPSIGN(twopk, BIAS + k); RETURNI(t * twopk); } else { SET_LDBL_EXPSIGN(twopk, BIAS + k + 10000); RETURNI(t * twopk * twom10000); } } /* * Our T1 and T2 are chosen to be approximately the points where method * A and method B have the same accuracy. Tang's T1 and T2 are the * points where method A's accuracy changes by a full bit. For Tang, * this drop in accuracy makes method A immediately less accurate than * method B, but our larger INTERVALS makes method A 2 bits more * accurate so it remains the most accurate method significantly * closer to the origin despite losing the full bit in our extended * range for it. * * Split the interval [T1, T2] into two intervals [T1, T3] and [T3, T2]. * Setting T3 to 0 would require the |x| < 0x1p-113 condition to appear * in both subintervals, so set T3 = 2**-5, which places the condition * into the [T1, T3] interval. * * XXX we now do this more to (partially) balance the number of terms * in the C and D polys than to avoid checking the condition in both * intervals. * * XXX these micro-optimizations are excessive. */ static const double T1 = -0.1659, /* ~-30.625/128 * log(2) */ T2 = 0.1659, /* ~30.625/128 * log(2) */ T3 = 0.03125; /* * Domain [-0.1659, 0.03125], range ~[2.9134e-44, 1.8404e-37]: * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-122.03 * * XXX none of the long double C or D coeffs except C10 is correctly printed. * If you re-print their values in %.35Le format, the result is always * different. For example, the last 2 digits in C3 should be 59, not 67. * 67 is apparently from rounding an extra-precision value to 36 decimal * places. */ static const long double C3 = 1.66666666666666666666666666666666667e-1L, C4 = 4.16666666666666666666666666666666645e-2L, C5 = 8.33333333333333333333333333333371638e-3L, C6 = 1.38888888888888888888888888891188658e-3L, C7 = 1.98412698412698412698412697235950394e-4L, C8 = 2.48015873015873015873015112487849040e-5L, C9 = 2.75573192239858906525606685484412005e-6L, C10 = 2.75573192239858906612966093057020362e-7L, C11 = 2.50521083854417203619031960151253944e-8L, C12 = 2.08767569878679576457272282566520649e-9L, C13 = 1.60590438367252471783548748824255707e-10L; /* * XXX this has 1 more coeff than needed. * XXX can start the double coeffs but not the double mults at C10. * With my coeffs (C10-C17 double; s = best_s): * Domain [-0.1659, 0.03125], range ~[-1.1976e-37, 1.1976e-37]: * |(exp(x)-1-x-x**2/2)/x - p(x)| ~< 2**-122.65 */ static const double C14 = 1.1470745580491932e-11, /* 0x1.93974a81dae30p-37 */ C15 = 7.6471620181090468e-13, /* 0x1.ae7f3820adab1p-41 */ C16 = 4.7793721460260450e-14, /* 0x1.ae7cd18a18eacp-45 */ C17 = 2.8074757356658877e-15, /* 0x1.949992a1937d9p-49 */ C18 = 1.4760610323699476e-16; /* 0x1.545b43aabfbcdp-53 */ /* * Domain [0.03125, 0.1659], range ~[-2.7676e-37, -1.0367e-38]: * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-121.44 */ static const long double D3 = 1.66666666666666666666666666666682245e-1L, D4 = 4.16666666666666666666666666634228324e-2L, D5 = 8.33333333333333333333333364022244481e-3L, D6 = 1.38888888888888888888887138722762072e-3L, D7 = 1.98412698412698412699085805424661471e-4L, D8 = 2.48015873015873015687993712101479612e-5L, D9 = 2.75573192239858944101036288338208042e-6L, D10 = 2.75573192239853161148064676533754048e-7L, D11 = 2.50521083855084570046480450935267433e-8L, D12 = 2.08767569819738524488686318024854942e-9L, D13 = 1.60590442297008495301927448122499313e-10L; /* * XXX this has 1 more coeff than needed. * XXX can start the double coeffs but not the double mults at D11. * With my coeffs (D11-D16 double): * Domain [0.03125, 0.1659], range ~[-1.1980e-37, 1.1980e-37]: * |(exp(x)-1-x-x**2/2)/x - p(x)| ~< 2**-122.65 */ static const double D14 = 1.1470726176204336e-11, /* 0x1.93971dc395d9ep-37 */ D15 = 7.6478532249581686e-13, /* 0x1.ae892e3D16fcep-41 */ D16 = 4.7628892832607741e-14, /* 0x1.ad00Dfe41feccp-45 */ D17 = 3.0524857220358650e-15; /* 0x1.D7e8d886Df921p-49 */ long double expm1l(long double x) { union IEEEl2bits u, v; long double hx2_hi, hx2_lo, q, r, r1, t, twomk, twopk, x_hi; long double x_lo, x2; double dr, dx, fn, r2; int k, n, n2; uint16_t hx, ix; /* Filter out exceptional cases. */ u.e = x; hx = u.xbits.expsign; ix = hx & 0x7fff; if (ix >= BIAS + 7) { /* |x| >= 128 or x is NaN */ if (ix == BIAS + LDBL_MAX_EXP) { if (hx & 0x8000) /* x is -Inf or -NaN */ RETURNF(-1 / x - 1); RETURNF(x + x); /* x is +Inf or +NaN */ } if (x > o_threshold) RETURNF(huge * huge); /* * expm1l() never underflows, but it must avoid * unrepresentable large negative exponents. We used a * much smaller threshold for large |x| above than in * expl() so as to handle not so large negative exponents * in the same way as large ones here. */ if (hx & 0x8000) /* x <= -128 */ RETURNF(tiny - 1); /* good for x < -114ln2 - eps */ } ENTERI(); if (T1 < x && x < T2) { x2 = x * x; dx = x; if (x < T3) { if (ix < BIAS - 113) { /* |x| < 0x1p-113 */ /* x (rounded) with inexact if x != 0: */ RETURNI(x == 0 ? x : (0x1p200 * x + fabsl(x)) * 0x1p-200); } q = x * x2 * C3 + x2 * x2 * (C4 + x * (C5 + x * (C6 + x * (C7 + x * (C8 + x * (C9 + x * (C10 + x * (C11 + x * (C12 + x * (C13 + dx * (C14 + dx * (C15 + dx * (C16 + dx * (C17 + dx * C18)))))))))))))); } else { q = x * x2 * D3 + x2 * x2 * (D4 + x * (D5 + x * (D6 + x * (D7 + x * (D8 + x * (D9 + x * (D10 + x * (D11 + x * (D12 + x * (D13 + dx * (D14 + dx * (D15 + dx * (D16 + dx * D17))))))))))))); } x_hi = (float)x; x_lo = x - x_hi; hx2_hi = x_hi * x_hi / 2; hx2_lo = x_lo * (x + x_hi) / 2; if (ix >= BIAS - 7) RETURNI((hx2_hi + x_hi) + (hx2_lo + x_lo + q)); else RETURNI(x + (hx2_lo + q + hx2_hi)); } /* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */ fn = rnint((double)x * INV_L); n = irint(fn); n2 = (unsigned)n % INTERVALS; k = n >> LOG2_INTERVALS; r1 = x - fn * L1; r2 = fn * -L2; r = r1 + r2; /* Prepare scale factor. */ v.e = 1; v.xbits.expsign = BIAS + k; twopk = v.e; /* * Evaluate lower terms of * expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */ dr = r; q = r2 + r * r * (A2 + r * (A3 + r * (A4 + r * (A5 + r * (A6 + dr * (A7 + dr * (A8 + dr * (A9 + dr * A10)))))))); t = tbl[n2].lo + tbl[n2].hi; if (k == 0) { t = SUM2P(tbl[n2].hi - 1, tbl[n2].lo * (r1 + 1) + t * q + tbl[n2].hi * r1); RETURNI(t); } if (k == -1) { t = SUM2P(tbl[n2].hi - 2, tbl[n2].lo * (r1 + 1) + t * q + tbl[n2].hi * r1); RETURNI(t / 2); } if (k < -7) { t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1)); RETURNI(t * twopk - 1); } if (k > 2 * LDBL_MANT_DIG - 1) { t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1)); if (k == LDBL_MAX_EXP) RETURNI(t * 2 * 0x1p16383L - 1); RETURNI(t * twopk - 1); } v.xbits.expsign = BIAS - k; twomk = v.e; if (k > LDBL_MANT_DIG - 1) t = SUM2P(tbl[n2].hi, tbl[n2].lo - twomk + t * (q + r1)); else t = SUM2P(tbl[n2].hi - twomk, tbl[n2].lo + t * (q + r1)); RETURNI(t * twopk); } diff --git a/lib/msun/ld128/s_logl.c b/lib/msun/ld128/s_logl.c index 8961dd0c96db..4d32462e5653 100644 --- a/lib/msun/ld128/s_logl.c +++ b/lib/msun/ld128/s_logl.c @@ -1,732 +1,731 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007-2013 Bruce D. Evans * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include /** * Implementation of the natural logarithm of x for 128-bit format. * * First decompose x into its base 2 representation: * * log(x) = log(X * 2**k), where X is in [1, 2) * = log(X) + k * log(2). * * Let X = X_i + e, where X_i is the center of one of the intervals * [-1.0/256, 1.0/256), [1.0/256, 3.0/256), .... [2.0-1.0/256, 2.0+1.0/256) * and X is in this interval. Then * * log(X) = log(X_i + e) * = log(X_i * (1 + e / X_i)) * = log(X_i) + log(1 + e / X_i). * * The values log(X_i) are tabulated below. Let d = e / X_i and use * * log(1 + d) = p(d) * * where p(d) = d - 0.5*d*d + ... is a special minimax polynomial of * suitably high degree. * * To get sufficiently small roundoff errors, k * log(2), log(X_i), and * sometimes (if |k| is not large) the first term in p(d) must be evaluated * and added up in extra precision. Extra precision is not needed for the * rest of p(d). In the worst case when k = 0 and log(X_i) is 0, the final * error is controlled mainly by the error in the second term in p(d). The * error in this term itself is at most 0.5 ulps from the d*d operation in * it. The error in this term relative to the first term is thus at most * 0.5 * |-0.5| * |d| < 1.0/1024 ulps. We aim for an accumulated error of * at most twice this at the point of the final rounding step. Thus the * final error should be at most 0.5 + 1.0/512 = 0.5020 ulps. Exhaustive * testing of a float variant of this function showed a maximum final error * of 0.5008 ulps. Non-exhaustive testing of a double variant of this * function showed a maximum final error of 0.5078 ulps (near 1+1.0/256). * * We made the maximum of |d| (and thus the total relative error and the * degree of p(d)) small by using a large number of intervals. Using * centers of intervals instead of endpoints reduces this maximum by a * factor of 2 for a given number of intervals. p(d) is special only * in beginning with the Taylor coefficients 0 + 1*d, which tends to happen * naturally. The most accurate minimax polynomial of a given degree might * be different, but then we wouldn't want it since we would have to do * extra work to avoid roundoff error (especially for P0*d instead of d). */ #ifdef DEBUG #include #include #endif #include "fpmath.h" #include "math.h" #ifndef NO_STRUCT_RETURN #define STRUCT_RETURN #endif #include "math_private.h" #if !defined(NO_UTAB) && !defined(NO_UTABL) #define USE_UTAB #endif /* * Domain [-0.005280, 0.004838], range ~[-1.1577e-37, 1.1582e-37]: * |log(1 + d)/d - p(d)| < 2**-122.7 */ static const long double P2 = -0.5L, P3 = 3.33333333333333333333333333333233795e-1L, /* 0x15555555555555555555555554d42.0p-114L */ P4 = -2.49999999999999999999999999941139296e-1L, /* -0x1ffffffffffffffffffffffdab14e.0p-115L */ P5 = 2.00000000000000000000000085468039943e-1L, /* 0x19999999999999999999a6d3567f4.0p-115L */ P6 = -1.66666666666666666666696142372698408e-1L, /* -0x15555555555555555567267a58e13.0p-115L */ P7 = 1.42857142857142857119522943477166120e-1L, /* 0x1249249249249248ed79a0ae434de.0p-115L */ P8 = -1.24999999999999994863289015033581301e-1L; /* -0x1fffffffffffffa13e91765e46140.0p-116L */ /* Double precision gives ~ 53 + log2(P9 * max(|d|)**8) ~= 120 bits. */ static const double P9 = 1.1111111111111401e-1, /* 0x1c71c71c71c7ed.0p-56 */ P10 = -1.0000000000040135e-1, /* -0x199999999a0a92.0p-56 */ P11 = 9.0909090728136258e-2, /* 0x1745d173962111.0p-56 */ P12 = -8.3333318851855284e-2, /* -0x1555551722c7a3.0p-56 */ P13 = 7.6928634666404178e-2, /* 0x13b1985204a4ae.0p-56 */ P14 = -7.1626810078462499e-2; /* -0x12562276cdc5d0.0p-56 */ static volatile const double zero = 0; #define INTERVALS 128 #define LOG2_INTERVALS 7 #define TSIZE (INTERVALS + 1) #define G(i) (T[(i)].G) #define F_hi(i) (T[(i)].F_hi) #define F_lo(i) (T[(i)].F_lo) #define ln2_hi F_hi(TSIZE - 1) #define ln2_lo F_lo(TSIZE - 1) #define E(i) (U[(i)].E) #define H(i) (U[(i)].H) static const struct { float G; /* 1/(1 + i/128) rounded to 8/9 bits */ float F_hi; /* log(1 / G_i) rounded (see below) */ /* The compiler will insert 8 bytes of padding here. */ long double F_lo; /* next 113 bits for log(1 / G_i) */ } T[TSIZE] = { /* * ln2_hi and each F_hi(i) are rounded to a number of bits that * makes F_hi(i) + dk*ln2_hi exact for all i and all dk. * * The last entry (for X just below 2) is used to define ln2_hi * and ln2_lo, to ensure that F_hi(i) and F_lo(i) cancel exactly * with dk*ln2_hi and dk*ln2_lo, respectively, when dk = -1. * This is needed for accuracy when x is just below 1. (To avoid * special cases, such x are "reduced" strangely to X just below * 2 and dk = -1, and then the exact cancellation is needed * because any the error from any non-exactness would be too * large). * * The relevant range of dk is [-16445, 16383]. The maximum number * of bits in F_hi(i) that works is very dependent on i but has * a minimum of 93. We only need about 12 bits in F_hi(i) for * it to provide enough extra precision. * * We round F_hi(i) to 24 bits so that it can have type float, * mainly to minimize the size of the table. Using all 24 bits * in a float for it automatically satisfies the above constraints. */ 0x800000.0p-23, 0, 0, 0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6674afa0c4bfe16e8fd.0p-144L, 0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83717be918e1119642ab.0p-144L, 0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173697cf302cc9476f561.0p-143L, 0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e78eba9b1113bc1c18.0p-142L, 0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7bfa509bec8da5f22.0p-142L, 0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a107674986dcdca6709c.0p-143L, 0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb958897a3ea46e84abb3.0p-142L, 0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c484993c549c4bf40.0p-151L, 0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560d9e9ab3d6ebab580.0p-141L, 0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d5037108f4ec21e48cd.0p-142L, 0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a70f7a684c596b12.0p-143L, 0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da99ded322fb08b8462.0p-141L, 0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150ae09996d7bb4653e.0p-143L, 0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251aefe0ded34c8318f52.0p-145L, 0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d56699c1799a244d4.0p-144L, 0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e6766abceccab1d7174.0p-141L, 0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f4215f93936b709efb.0p-142L, 0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6affd511b534b72a28e.0p-140L, 0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1d9b2ef7e68680598.0p-143L, 0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b3f46662238a9425a.0p-142L, 0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9691aed4d5e3df94.0p-140L, 0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c46c186384993e1c93.0p-142L, 0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e5697dc6a402a56fce1.0p-141L, 0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba9367707ebfa540e45350c.0p-144L, 0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d31ef0f4c9d43f79b2.0p-140L, 0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b75e7d900b521c48d.0p-141L, 0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06508aeb00d2ae3e9.0p-140L, 0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3af80485c2f409633c.0p-142L, 0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d686581799fbce0b5f19.0p-141L, 0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae54f550444ecf8b995.0p-140L, 0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc4595412b5d2517aaac13.0p-141L, 0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d3a85b5b43c0e727.0p-141L, 0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df841a71b79dd5645b46.0p-145L, 0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe0bcfbe6d6db9f66.0p-147L, 0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa6911c7bafcb4d84fb.0p-141L, 0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb328337cc050c6d83b22.0p-140L, 0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e5fcf1a212e2a91e.0p-139L, 0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f465e5ecab5f2a6f81.0p-139L, 0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a0fe396f40f1dda9.0p-141L, 0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de945a049a962e66c6.0p-139L, 0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5147bdb6ddcaf59c425.0p-141L, 0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba46bae9827221dc98.0p-139L, 0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b730e28aba001a9b5e0.0p-140L, 0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed72e23e13431adc4a5.0p-141L, 0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7148e8d80caa10b7.0p-139L, 0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c5663663d15faed7771.0p-139L, 0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb2438273918db7df5c.0p-141L, 0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698298adddd7f32686.0p-141L, 0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123615b147a5d47bc208f.0p-142L, 0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b263acb4351104631.0p-140L, 0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a42423457e22d8c650b355.0p-139L, 0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a465dc513b13f567d.0p-143L, 0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770633947ffe651e7352f.0p-139L, 0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b15228bfe8798d10ff0.0p-142L, 0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f088b61a335f5b688c.0p-140L, 0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad88e7d353e9967d548.0p-139L, 0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf45de06ecebfaf6d.0p-139L, 0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab904864092b34edda19a831e.0p-140L, 0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333221d8a9b475a6ba.0p-139L, 0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fbfe24b633f4e8d84d.0p-140L, 0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c89c45003fc5d7807.0p-140L, 0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8002f2449e174504.0p-139L, 0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a8717d5626e16acc7d.0p-141L, 0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3ca87dabf351aa41f4.0p-139L, 0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d79f51dcc73014c9.0p-141L, 0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac42d1bf9199188e7.0p-141L, 0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549dd1160bcc45c7e2c.0p-139L, 0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b610665377f15625b6.0p-140L, 0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a2d1b2176010478be.0p-140L, 0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f0c95dd83626d7333.0p-142L, 0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b67ccb006a5b9890ea.0p-140L, 0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f56db28da4d629d00a.0p-140L, 0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d8f4d60c713346641.0p-140L, 0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d3b3d406b6cbf3ce5.0p-140L, 0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd73692609040ccc2.0p-139L, 0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f7301901b8ad85c25afd09.0p-139L, 0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cc8a4dfb804de6867.0p-140L, 0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d42f78d3e65d3727.0p-141L, 0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af269647b783d88999.0p-139L, 0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e063714615f7cc91d.0p-144L, 0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade02951686d5373aec.0p-139L, 0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1649349630531502.0p-139L, 0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c5320619fb9433d841.0p-139L, 0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f0bdff99f932b273.0p-138L, 0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e54e78103a2bc1767.0p-141L, 0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b7d7f47ddb45c5a3.0p-139L, 0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb82873b04a9af1dd692c.0p-138L, 0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9b9770d8cb6573540.0p-138L, 0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f002e836dfd47bd41.0p-139L, 0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd5cd7cc94306fb3ff.0p-140L, 0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de2b41eeebd550702.0p-138L, 0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f45275c917a30df4ac9.0p-138L, 0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af71a89df4e6df2e93b.0p-139L, 0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfdec367828734cae5.0p-139L, 0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f76b87333891e0dec4.0p-138L, 0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a263e3bf446c6e3f69.0p-140L, 0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d723a4c7380a448d8.0p-139L, 0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3236f330972da2a7a87.0p-139L, 0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d21148c6002becd3.0p-139L, 0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c336af90e00533323ba.0p-139L, 0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf2f105a89060046aa.0p-138L, 0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf162409d8ea99d4c0.0p-139L, 0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507b9dc10dac743ad7a.0p-138L, 0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e97c4990b23d9ac1f5.0p-139L, 0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea74540bdd2aa99a42.0p-138L, 0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f9527e6aba8f2d783c1.0p-138L, 0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe7ba81c664c107e0.0p-138L, 0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576aad348ae79867223.0p-138L, 0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a246726b304ccae56.0p-139L, 0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c2f9b47466d6123fe.0p-139L, 0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f38b4619a2483399.0p-141L, 0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3597043be78eaf49.0p-139L, 0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d204147dc69a07a649.0p-138L, 0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c008d3602a7b41c6e8.0p-139L, 0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541aca7d5844606b2421.0p-139L, 0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4571acbcfb03f16daf4.0p-138L, 0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c0a345ad743ae1ae.0p-140L, 0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d749362382a7688479e24.0p-140L, 0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce532661ea9643a3a2d378.0p-139L, 0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d257530a682b80490.0p-139L, 0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b35ba3e1f868fd0b5e.0p-140L, 0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3303dd481779df69.0p-139L, 0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900345a85d2d86161742e.0p-140L, 0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f79b026b64b42caa1.0p-140L, 0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a82ab19f77652d977a.0p-141L, 0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b48d7b98c1cf7234.0p-138L, 0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a197e9c7359dd94152f.0p-138L, 0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c3898cff81a12a17e2.0p-141L, }; #ifdef USE_UTAB static const struct { float H; /* 1 + i/INTERVALS (exact) */ float E; /* H(i) * G(i) - 1 (exact) */ } U[TSIZE] = { 0x800000.0p-23, 0, 0x810000.0p-23, -0x800000.0p-37, 0x820000.0p-23, -0x800000.0p-35, 0x830000.0p-23, -0x900000.0p-34, 0x840000.0p-23, -0x800000.0p-33, 0x850000.0p-23, -0xc80000.0p-33, 0x860000.0p-23, -0xa00000.0p-36, 0x870000.0p-23, 0x940000.0p-33, 0x880000.0p-23, 0x800000.0p-35, 0x890000.0p-23, -0xc80000.0p-34, 0x8a0000.0p-23, 0xe00000.0p-36, 0x8b0000.0p-23, 0x900000.0p-33, 0x8c0000.0p-23, -0x800000.0p-35, 0x8d0000.0p-23, -0xe00000.0p-33, 0x8e0000.0p-23, 0x880000.0p-33, 0x8f0000.0p-23, -0xa80000.0p-34, 0x900000.0p-23, -0x800000.0p-35, 0x910000.0p-23, 0x800000.0p-37, 0x920000.0p-23, 0x900000.0p-35, 0x930000.0p-23, 0xd00000.0p-35, 0x940000.0p-23, 0xe00000.0p-35, 0x950000.0p-23, 0xc00000.0p-35, 0x960000.0p-23, 0xe00000.0p-36, 0x970000.0p-23, -0x800000.0p-38, 0x980000.0p-23, -0xc00000.0p-35, 0x990000.0p-23, -0xd00000.0p-34, 0x9a0000.0p-23, 0x880000.0p-33, 0x9b0000.0p-23, 0xe80000.0p-35, 0x9c0000.0p-23, -0x800000.0p-35, 0x9d0000.0p-23, 0xb40000.0p-33, 0x9e0000.0p-23, 0x880000.0p-34, 0x9f0000.0p-23, -0xe00000.0p-35, 0xa00000.0p-23, 0x800000.0p-33, 0xa10000.0p-23, -0x900000.0p-36, 0xa20000.0p-23, -0xb00000.0p-33, 0xa30000.0p-23, -0xa00000.0p-36, 0xa40000.0p-23, 0x800000.0p-33, 0xa50000.0p-23, -0xf80000.0p-35, 0xa60000.0p-23, 0x880000.0p-34, 0xa70000.0p-23, -0x900000.0p-33, 0xa80000.0p-23, -0x800000.0p-35, 0xa90000.0p-23, 0x900000.0p-34, 0xaa0000.0p-23, 0xa80000.0p-33, 0xab0000.0p-23, -0xac0000.0p-34, 0xac0000.0p-23, -0x800000.0p-37, 0xad0000.0p-23, 0xf80000.0p-35, 0xae0000.0p-23, 0xf80000.0p-34, 0xaf0000.0p-23, -0xac0000.0p-33, 0xb00000.0p-23, -0x800000.0p-33, 0xb10000.0p-23, -0xb80000.0p-34, 0xb20000.0p-23, -0x800000.0p-34, 0xb30000.0p-23, -0xb00000.0p-35, 0xb40000.0p-23, -0x800000.0p-35, 0xb50000.0p-23, -0xe00000.0p-36, 0xb60000.0p-23, -0x800000.0p-35, 0xb70000.0p-23, -0xb00000.0p-35, 0xb80000.0p-23, -0x800000.0p-34, 0xb90000.0p-23, -0xb80000.0p-34, 0xba0000.0p-23, -0x800000.0p-33, 0xbb0000.0p-23, -0xac0000.0p-33, 0xbc0000.0p-23, 0x980000.0p-33, 0xbd0000.0p-23, 0xbc0000.0p-34, 0xbe0000.0p-23, 0xe00000.0p-36, 0xbf0000.0p-23, -0xb80000.0p-35, 0xc00000.0p-23, -0x800000.0p-33, 0xc10000.0p-23, 0xa80000.0p-33, 0xc20000.0p-23, 0x900000.0p-34, 0xc30000.0p-23, -0x800000.0p-35, 0xc40000.0p-23, -0x900000.0p-33, 0xc50000.0p-23, 0x820000.0p-33, 0xc60000.0p-23, 0x800000.0p-38, 0xc70000.0p-23, -0x820000.0p-33, 0xc80000.0p-23, 0x800000.0p-33, 0xc90000.0p-23, -0xa00000.0p-36, 0xca0000.0p-23, -0xb00000.0p-33, 0xcb0000.0p-23, 0x840000.0p-34, 0xcc0000.0p-23, -0xd00000.0p-34, 0xcd0000.0p-23, 0x800000.0p-33, 0xce0000.0p-23, -0xe00000.0p-35, 0xcf0000.0p-23, 0xa60000.0p-33, 0xd00000.0p-23, -0x800000.0p-35, 0xd10000.0p-23, 0xb40000.0p-33, 0xd20000.0p-23, -0x800000.0p-35, 0xd30000.0p-23, 0xaa0000.0p-33, 0xd40000.0p-23, -0xe00000.0p-35, 0xd50000.0p-23, 0x880000.0p-33, 0xd60000.0p-23, -0xd00000.0p-34, 0xd70000.0p-23, 0x9c0000.0p-34, 0xd80000.0p-23, -0xb00000.0p-33, 0xd90000.0p-23, -0x800000.0p-38, 0xda0000.0p-23, 0xa40000.0p-33, 0xdb0000.0p-23, -0xdc0000.0p-34, 0xdc0000.0p-23, 0xc00000.0p-35, 0xdd0000.0p-23, 0xca0000.0p-33, 0xde0000.0p-23, -0xb80000.0p-34, 0xdf0000.0p-23, 0xd00000.0p-35, 0xe00000.0p-23, 0xc00000.0p-33, 0xe10000.0p-23, -0xf40000.0p-34, 0xe20000.0p-23, 0x800000.0p-37, 0xe30000.0p-23, 0x860000.0p-33, 0xe40000.0p-23, -0xc80000.0p-33, 0xe50000.0p-23, -0xa80000.0p-34, 0xe60000.0p-23, 0xe00000.0p-36, 0xe70000.0p-23, 0x880000.0p-33, 0xe80000.0p-23, -0xe00000.0p-33, 0xe90000.0p-23, -0xfc0000.0p-34, 0xea0000.0p-23, -0x800000.0p-35, 0xeb0000.0p-23, 0xe80000.0p-35, 0xec0000.0p-23, 0x900000.0p-33, 0xed0000.0p-23, 0xe20000.0p-33, 0xee0000.0p-23, -0xac0000.0p-33, 0xef0000.0p-23, -0xc80000.0p-34, 0xf00000.0p-23, -0x800000.0p-35, 0xf10000.0p-23, 0x800000.0p-35, 0xf20000.0p-23, 0xb80000.0p-34, 0xf30000.0p-23, 0x940000.0p-33, 0xf40000.0p-23, 0xc80000.0p-33, 0xf50000.0p-23, -0xf20000.0p-33, 0xf60000.0p-23, -0xc80000.0p-33, 0xf70000.0p-23, -0xa20000.0p-33, 0xf80000.0p-23, -0x800000.0p-33, 0xf90000.0p-23, -0xc40000.0p-34, 0xfa0000.0p-23, -0x900000.0p-34, 0xfb0000.0p-23, -0xc80000.0p-35, 0xfc0000.0p-23, -0x800000.0p-35, 0xfd0000.0p-23, -0x900000.0p-36, 0xfe0000.0p-23, -0x800000.0p-37, 0xff0000.0p-23, -0x800000.0p-39, 0x800000.0p-22, 0, }; #endif /* USE_UTAB */ #ifdef STRUCT_RETURN #define RETURN1(rp, v) do { \ (rp)->hi = (v); \ (rp)->lo_set = 0; \ return; \ } while (0) #define RETURN2(rp, h, l) do { \ (rp)->hi = (h); \ (rp)->lo = (l); \ (rp)->lo_set = 1; \ return; \ } while (0) struct ld { long double hi; long double lo; int lo_set; }; #else #define RETURN1(rp, v) RETURNF(v) #define RETURN2(rp, h, l) RETURNI((h) + (l)) #endif #ifdef STRUCT_RETURN static inline __always_inline void k_logl(long double x, struct ld *rp) #else long double logl(long double x) #endif { long double d, val_hi, val_lo; double dd, dk; uint64_t lx, llx; int i, k; uint16_t hx; EXTRACT_LDBL128_WORDS(hx, lx, llx, x); k = -16383; #if 0 /* Hard to do efficiently. Don't do it until we support all modes. */ if (x == 1) RETURN1(rp, 0); /* log(1) = +0 in all rounding modes */ #endif if (hx == 0 || hx >= 0x8000) { /* zero, negative or subnormal? */ if (((hx & 0x7fff) | lx | llx) == 0) RETURN1(rp, -1 / zero); /* log(+-0) = -Inf */ if (hx != 0) /* log(neg or NaN) = qNaN: */ RETURN1(rp, (x - x) / zero); x *= 0x1.0p113; /* subnormal; scale up x */ EXTRACT_LDBL128_WORDS(hx, lx, llx, x); k = -16383 - 113; } else if (hx >= 0x7fff) RETURN1(rp, x + x); /* log(Inf or NaN) = Inf or qNaN */ #ifndef STRUCT_RETURN ENTERI(); #endif k += hx; dk = k; /* Scale x to be in [1, 2). */ SET_LDBL_EXPSIGN(x, 0x3fff); /* 0 <= i <= INTERVALS: */ #define L2I (49 - LOG2_INTERVALS) i = (lx + (1LL << (L2I - 2))) >> (L2I - 1); /* * -0.005280 < d < 0.004838. In particular, the infinite- * precision |d| is <= 2**-7. Rounding of G(i) to 8 bits * ensures that d is representable without extra precision for * this bound on |d| (since when this calculation is expressed * as x*G(i)-1, the multiplication needs as many extra bits as * G(i) has and the subtraction cancels 8 bits). But for * most i (107 cases out of 129), the infinite-precision |d| * is <= 2**-8. G(i) is rounded to 9 bits for such i to give * better accuracy (this works by improving the bound on |d|, * which in turn allows rounding to 9 bits in more cases). * This is only important when the original x is near 1 -- it * lets us avoid using a special method to give the desired * accuracy for such x. */ if (0) d = x * G(i) - 1; else { #ifdef USE_UTAB d = (x - H(i)) * G(i) + E(i); #else long double x_hi; double x_lo; /* * Split x into x_hi + x_lo to calculate x*G(i)-1 exactly. * G(i) has at most 9 bits, so the splitting point is not * critical. */ INSERT_LDBL128_WORDS(x_hi, 0x3fff, lx, llx & 0xffffffffff000000ULL); x_lo = x - x_hi; d = x_hi * G(i) - 1 + x_lo * G(i); #endif } /* * Our algorithm depends on exact cancellation of F_lo(i) and * F_hi(i) with dk*ln_2_lo and dk*ln2_hi when k is -1 and i is * at the end of the table. This and other technical complications * make it difficult to avoid the double scaling in (dk*ln2) * * log(base) for base != e without losing more accuracy and/or * efficiency than is gained. */ /* * Use double precision operations wherever possible, since * long double operations are emulated and were very slow on * the old sparc64 and unknown on the newer aarch64 and riscv * machines. Also, don't try to improve parallelism by * increasing the number of operations, since any parallelism * on such machines is needed for the emulation. Horner's * method is good for this, and is also good for accuracy. * Horner's method doesn't handle the `lo' term well, either * for efficiency or accuracy. However, for accuracy we * evaluate d * d * P2 separately to take advantage of by P2 * being exact, and this gives a good place to sum the 'lo' * term too. */ dd = (double)d; val_lo = d * d * d * (P3 + d * (P4 + d * (P5 + d * (P6 + d * (P7 + d * (P8 + dd * (P9 + dd * (P10 + dd * (P11 + dd * (P12 + dd * (P13 + dd * P14))))))))))) + (F_lo(i) + dk * ln2_lo) + d * d * P2; val_hi = d; #ifdef DEBUG if (fetestexcept(FE_UNDERFLOW)) breakpoint(); #endif _3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi); RETURN2(rp, val_hi, val_lo); } long double log1pl(long double x) { long double d, d_hi, f_lo, val_hi, val_lo; long double f_hi, twopminusk; double d_lo, dd, dk; uint64_t lx, llx; int i, k; int16_t ax, hx; EXTRACT_LDBL128_WORDS(hx, lx, llx, x); if (hx < 0x3fff) { /* x < 1, or x neg NaN */ ax = hx & 0x7fff; if (ax >= 0x3fff) { /* x <= -1, or x neg NaN */ if (ax == 0x3fff && (lx | llx) == 0) RETURNF(-1 / zero); /* log1p(-1) = -Inf */ /* log1p(x < 1, or x NaN) = qNaN: */ RETURNF((x - x) / (x - x)); } if (ax <= 0x3f8d) { /* |x| < 2**-113 */ if ((int)x == 0) RETURNF(x); /* x with inexact if x != 0 */ } f_hi = 1; f_lo = x; } else if (hx >= 0x7fff) { /* x +Inf or non-neg NaN */ RETURNF(x + x); /* log1p(Inf or NaN) = Inf or qNaN */ } else if (hx < 0x40e1) { /* 1 <= x < 2**226 */ f_hi = x; f_lo = 1; } else { /* 2**226 <= x < +Inf */ f_hi = x; f_lo = 0; /* avoid underflow of the P3 term */ } ENTERI(); x = f_hi + f_lo; f_lo = (f_hi - x) + f_lo; EXTRACT_LDBL128_WORDS(hx, lx, llx, x); k = -16383; k += hx; dk = k; SET_LDBL_EXPSIGN(x, 0x3fff); twopminusk = 1; SET_LDBL_EXPSIGN(twopminusk, 0x7ffe - (hx & 0x7fff)); f_lo *= twopminusk; i = (lx + (1LL << (L2I - 2))) >> (L2I - 1); /* * x*G(i)-1 (with a reduced x) can be represented exactly, as * above, but now we need to evaluate the polynomial on d = * (x+f_lo)*G(i)-1 and extra precision is needed for that. * Since x+x_lo is a hi+lo decomposition and subtracting 1 * doesn't lose too many bits, an inexact calculation for * f_lo*G(i) is good enough. */ if (0) d_hi = x * G(i) - 1; else { #ifdef USE_UTAB d_hi = (x - H(i)) * G(i) + E(i); #else long double x_hi; double x_lo; INSERT_LDBL128_WORDS(x_hi, 0x3fff, lx, llx & 0xffffffffff000000ULL); x_lo = x - x_hi; d_hi = x_hi * G(i) - 1 + x_lo * G(i); #endif } d_lo = f_lo * G(i); /* * This is _2sumF(d_hi, d_lo) inlined. The condition * (d_hi == 0 || |d_hi| >= |d_lo|) for using _2sumF() is not * always satisifed, so it is not clear that this works, but * it works in practice. It works even if it gives a wrong * normalized d_lo, since |d_lo| > |d_hi| implies that i is * nonzero and d is tiny, so the F(i) term dominates d_lo. * In float precision: * (By exhaustive testing, the worst case is d_hi = 0x1.bp-25. * And if d is only a little tinier than that, we would have * another underflow problem for the P3 term; this is also ruled * out by exhaustive testing.) */ d = d_hi + d_lo; d_lo = d_hi - d + d_lo; d_hi = d; dd = (double)d; val_lo = d * d * d * (P3 + d * (P4 + d * (P5 + d * (P6 + d * (P7 + d * (P8 + dd * (P9 + dd * (P10 + dd * (P11 + dd * (P12 + dd * (P13 + dd * P14))))))))))) + (F_lo(i) + dk * ln2_lo + d_lo) + d * d * P2; val_hi = d_hi; #ifdef DEBUG if (fetestexcept(FE_UNDERFLOW)) breakpoint(); #endif _3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi); RETURNI(val_hi + val_lo); } #ifdef STRUCT_RETURN long double logl(long double x) { struct ld r; ENTERI(); k_logl(x, &r); RETURNSPI(&r); } /* * 29+113 bit decompositions. The bits are distributed so that the products * of the hi terms are exact in double precision. The types are chosen so * that the products of the hi terms are done in at least double precision, * without any explicit conversions. More natural choices would require a * slow long double precision multiplication. */ static const double invln10_hi = 4.3429448176175356e-1, /* 0x1bcb7b15000000.0p-54 */ invln2_hi = 1.4426950402557850e0; /* 0x17154765000000.0p-52 */ static const long double invln10_lo = 1.41498268538580090791605082294397000e-10L, /* 0x137287195355baaafad33dc323ee3.0p-145L */ invln2_lo = 6.33178418956604368501892137426645911e-10L, /* 0x15c17f0bbbe87fed0691d3e88eb57.0p-143L */ invln10_lo_plus_hi = invln10_lo + invln10_hi, invln2_lo_plus_hi = invln2_lo + invln2_hi; long double log10l(long double x) { struct ld r; long double hi, lo; ENTERI(); k_logl(x, &r); if (!r.lo_set) RETURNI(r.hi); _2sumF(r.hi, r.lo); hi = (float)r.hi; lo = r.lo + (r.hi - hi); RETURNI(invln10_hi * hi + (invln10_lo_plus_hi * lo + invln10_lo * hi)); } long double log2l(long double x) { struct ld r; long double hi, lo; ENTERI(); k_logl(x, &r); if (!r.lo_set) RETURNI(r.hi); _2sumF(r.hi, r.lo); hi = (float)r.hi; lo = r.lo + (r.hi - hi); RETURNI(invln2_hi * hi + (invln2_lo_plus_hi * lo + invln2_lo * hi)); } #endif /* STRUCT_RETURN */ diff --git a/lib/msun/ld80/e_lgammal_r.c b/lib/msun/ld80/e_lgammal_r.c index cfd73b408b87..8bac285c97d6 100644 --- a/lib/msun/ld80/e_lgammal_r.c +++ b/lib/msun/ld80/e_lgammal_r.c @@ -1,356 +1,355 @@ /* @(#)e_lgamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_lgamma_r.c for complete comments. * * Converted to long double by Steven G. Kargl. */ #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" static const volatile double vzero = 0; static const double zero= 0, half= 0.5, one = 1; static const union IEEEl2bits piu = LD80C(0xc90fdaa22168c235, 1, 3.14159265358979323851e+00L); #define pi (piu.e) /* * Domain y in [0x1p-70, 0.27], range ~[-4.5264e-22, 4.5264e-22]: * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-70.9 */ static const union IEEEl2bits a0u = LD80C(0x9e233f1bed863d26, -4, 7.72156649015328606028e-02L), a1u = LD80C(0xa51a6625307d3249, -2, 3.22467033424113218889e-01L), a2u = LD80C(0x89f000d2abafda8c, -4, 6.73523010531979398946e-02L), a3u = LD80C(0xa8991563eca75f26, -6, 2.05808084277991211934e-02L), a4u = LD80C(0xf2027e10634ce6b6, -8, 7.38555102796070454026e-03L), a5u = LD80C(0xbd6eb76dd22187f4, -9, 2.89051035162703932972e-03L), a6u = LD80C(0x9c562ab05e0458ed, -10, 1.19275351624639999297e-03L), a7u = LD80C(0x859baed93ee48e46, -11, 5.09674593842117925320e-04L), a8u = LD80C(0xe9f28a4432949af2, -13, 2.23109648015769155122e-04L), a9u = LD80C(0xd12ad0d9b93c6bb0, -14, 9.97387167479808509830e-05L), a10u= LD80C(0xb7522643c78a219b, -15, 4.37071076331030136818e-05L), a11u= LD80C(0xca024dcdece2cb79, -16, 2.40813493372040143061e-05L), a12u= LD80C(0xbb90fb6968ebdbf9, -19, 2.79495621083634031729e-06L), a13u= LD80C(0xba1c9ffeeae07b37, -17, 1.10931287015513924136e-05L); #define a0 (a0u.e) #define a1 (a1u.e) #define a2 (a2u.e) #define a3 (a3u.e) #define a4 (a4u.e) #define a5 (a5u.e) #define a6 (a6u.e) #define a7 (a7u.e) #define a8 (a8u.e) #define a9 (a9u.e) #define a10 (a10u.e) #define a11 (a11u.e) #define a12 (a12u.e) #define a13 (a13u.e) /* * Domain x in [tc-0.24, tc+0.28], range ~[-6.1205e-22, 6.1205e-22]: * |(lgamma(x) - tf) - t(x - tc)| < 2**-70.5 */ static const union IEEEl2bits tcu = LD80C(0xbb16c31ab5f1fb71, 0, 1.46163214496836234128e+00L), tfu = LD80C(0xf8cdcde61c520e0f, -4, -1.21486290535849608093e-01L), ttu = LD80C(0xd46ee54b27d4de99, -69, -2.81152980996018785880e-21L), t0u = LD80C(0x80b9406556a62a6b, -68, 3.40728634996055147231e-21L), t1u = LD80C(0xc7e9c6f6df3f8c39, -67, -1.05833162742737073665e-20L), t2u = LD80C(0xf7b95e4771c55d51, -2, 4.83836122723810583532e-01L), t3u = LD80C(0x97213c6e35e119ff, -3, -1.47587722994530691476e-01L), t4u = LD80C(0x845a14a6a81dc94b, -4, 6.46249402389135358063e-02L), t5u = LD80C(0x864d46fa89997796, -5, -3.27885410884846056084e-02L), t6u = LD80C(0x93373cbd00297438, -6, 1.79706751150707171293e-02L), t7u = LD80C(0xa8fcfca7eddc8d1d, -7, -1.03142230361450732547e-02L), t8u = LD80C(0xc7e7015ff4bc45af, -8, 6.10053603296546099193e-03L), t9u = LD80C(0xf178d2247adc5093, -9, -3.68456964904901200152e-03L), t10u = LD80C(0x94188d58f12e5e9f, -9, 2.25976420273774583089e-03L), t11u = LD80C(0xb7cbaef14e1406f1, -10, -1.40224943666225639823e-03L), t12u = LD80C(0xe63a671e6704ea4d, -11, 8.78250640744776944887e-04L), t13u = LD80C(0x914b6c9cae61783e, -11, -5.54255012657716808811e-04L), t14u = LD80C(0xb858f5bdb79276fe, -12, 3.51614951536825927370e-04L), t15u = LD80C(0xea73e744c34b9591, -13, -2.23591563824520112236e-04L), t16u = LD80C(0x99aeabb0d67ba835, -13, 1.46562869351659194136e-04L), t17u = LD80C(0xd7c6938325db2024, -14, -1.02889866046435680588e-04L), t18u = LD80C(0xe24cb1e3b0474775, -15, 5.39540265505221957652e-05L); #define tc (tcu.e) #define tf (tfu.e) #define tt (ttu.e) #define t0 (t0u.e) #define t1 (t1u.e) #define t2 (t2u.e) #define t3 (t3u.e) #define t4 (t4u.e) #define t5 (t5u.e) #define t6 (t6u.e) #define t7 (t7u.e) #define t8 (t8u.e) #define t9 (t9u.e) #define t10 (t10u.e) #define t11 (t11u.e) #define t12 (t12u.e) #define t13 (t13u.e) #define t14 (t14u.e) #define t15 (t15u.e) #define t16 (t16u.e) #define t17 (t17u.e) #define t18 (t18u.e) /* * Domain y in [-0.1, 0.232], range ~[-8.1938e-22, 8.3815e-22]: * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-71.2 */ static const union IEEEl2bits u0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L), u1u = LD80C(0x98280ee45e4ddd3d, -1, 5.94361239198682739769e-01L), u2u = LD80C(0xe330c8ead4130733, 0, 1.77492629495841234275e+00L), u3u = LD80C(0xd4a213f1a002ec52, 0, 1.66119622514818078064e+00L), u4u = LD80C(0xa5a9ca6f5bc62163, -1, 6.47122051417476492989e-01L), u5u = LD80C(0xc980e49cd5b019e6, -4, 9.83903751718671509455e-02L), u6u = LD80C(0xff636a8bdce7025b, -9, 3.89691687802305743450e-03L), v1u = LD80C(0xbd109c533a19fbf5, 1, 2.95413883330948556544e+00L), v2u = LD80C(0xd295cbf96f31f099, 1, 3.29039286955665403176e+00L), v3u = LD80C(0xdab8bcfee40496cb, 0, 1.70876276441416471410e+00L), v4u = LD80C(0xd2f2dc3638567e9f, -2, 4.12009126299534668571e-01L), v5u = LD80C(0xa07d9b0851070f41, -5, 3.91822868305682491442e-02L), v6u = LD80C(0xe3cd8318f7adb2c4, -11, 8.68998648222144351114e-04L); #define u0 (u0u.e) #define u1 (u1u.e) #define u2 (u2u.e) #define u3 (u3u.e) #define u4 (u4u.e) #define u5 (u5u.e) #define u6 (u6u.e) #define v1 (v1u.e) #define v2 (v2u.e) #define v3 (v3u.e) #define v4 (v4u.e) #define v5 (v5u.e) #define v6 (v6u.e) /* * Domain x in (2, 3], range ~[-3.3648e-22, 3.4416e-22]: * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-72.3 * with y = x - 2. */ static const union IEEEl2bits s0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L), s1u = LD80C(0xd3ff0dcc7fa91f94, -3, 2.07027640921219389860e-01L), s2u = LD80C(0xb2bb62782478ef31, -2, 3.49085881391362090549e-01L), s3u = LD80C(0xb49f7438c4611a74, -3, 1.76389518704213357954e-01L), s4u = LD80C(0x9a957008fa27ecf9, -5, 3.77401710862930008071e-02L), s5u = LD80C(0xda9b389a6ca7a7ac, -9, 3.33566791452943399399e-03L), s6u = LD80C(0xbc7a2263faf59c14, -14, 8.98728786745638844395e-05L), r1u = LD80C(0xbf5cff5b11477d4d, 0, 1.49502555796294337722e+00L), r2u = LD80C(0xd9aec89de08e3da6, -1, 8.50323236984473285866e-01L), r3u = LD80C(0xeab7ae5057c443f9, -3, 2.29216312078225806131e-01L), r4u = LD80C(0xf29707d9bd2b1e37, -6, 2.96130326586640089145e-02L), r5u = LD80C(0xd376c2f09736c5a3, -10, 1.61334161411590662495e-03L), r6u = LD80C(0xc985983d0cd34e3d, -16, 2.40232770710953450636e-05L), r7u = LD80C(0xe5c7a4f7fc2ef13d, -25, -5.34997929289167573510e-08L); #define s0 (s0u.e) #define s1 (s1u.e) #define s2 (s2u.e) #define s3 (s3u.e) #define s4 (s4u.e) #define s5 (s5u.e) #define s6 (s6u.e) #define r1 (r1u.e) #define r2 (r2u.e) #define r3 (r3u.e) #define r4 (r4u.e) #define r5 (r5u.e) #define r6 (r6u.e) #define r7 (r7u.e) /* * Domain z in [8, 0x1p70], range ~[-3.0235e-22, 3.0563e-22]: * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-71.7 */ static const union IEEEl2bits w0u = LD80C(0xd67f1c864beb4a69, -2, 4.18938533204672741776e-01L), w1u = LD80C(0xaaaaaaaaaaaaaaa1, -4, 8.33333333333333332678e-02L), w2u = LD80C(0xb60b60b60b5491c9, -9, -2.77777777777760927870e-03L), w3u = LD80C(0xd00d00cf58aede4c, -11, 7.93650793490637233668e-04L), w4u = LD80C(0x9c09bf626783d4a5, -11, -5.95238023926039051268e-04L), w5u = LD80C(0xdca7cadc5baa517b, -11, 8.41733700408000822962e-04L), w6u = LD80C(0xfb060e361e1ffd07, -10, -1.91515849570245136604e-03L), w7u = LD80C(0xcbd5101bb58d1f2b, -8, 6.22046743903262649294e-03L), w8u = LD80C(0xad27a668d32c821b, -6, -2.11370706734662081843e-02L); #define w0 (w0u.e) #define w1 (w1u.e) #define w2 (w2u.e) #define w3 (w3u.e) #define w4 (w4u.e) #define w5 (w5u.e) #define w6 (w6u.e) #define w7 (w7u.e) #define w8 (w8u.e) static long double sin_pil(long double x) { volatile long double vz; long double y,z; uint64_t n; uint16_t hx; y = -x; vz = y+0x1p63; z = vz-0x1p63; if (z == y) return zero; vz = y+0x1p61; EXTRACT_LDBL80_WORDS(hx,n,vz); z = vz-0x1p61; if (z > y) { z -= 0.25; /* adjust to round down */ n--; } n &= 7; /* octant of y mod 2 */ y = y - z + n * 0.25; /* y mod 2 */ switch (n) { case 0: y = __kernel_sinl(pi*y,zero,0); break; case 1: case 2: y = __kernel_cosl(pi*(0.5-y),zero); break; case 3: case 4: y = __kernel_sinl(pi*(one-y),zero,0); break; case 5: case 6: y = -__kernel_cosl(pi*(y-1.5),zero); break; default: y = __kernel_sinl(pi*(y-2.0),zero,0); break; } return -y; } long double lgammal_r(long double x, int *signgamp) { long double nadj,p,p1,p2,q,r,t,w,y,z; uint64_t lx; int i; uint16_t hx,ix; EXTRACT_LDBL80_WORDS(hx,lx,x); /* purge +-Inf and NaNs */ *signgamp = 1; ix = hx&0x7fff; if(ix==0x7fff) return x*x; ENTERI(); /* purge +-0 and tiny arguments */ *signgamp = 1-2*(hx>>15); if(ix<0x3fff-67) { /* |x|<2**-(p+3), return -log(|x|) */ if((ix|lx)==0) RETURNI(one/vzero); RETURNI(-logl(fabsl(x))); } /* purge negative integers and start evaluation for other x < 0 */ if(hx&0x8000) { *signgamp = 1; if(ix>=0x3fff+63) /* |x|>=2**(p-1), must be -integer */ RETURNI(one/vzero); t = sin_pil(x); if(t==zero) RETURNI(one/vzero); /* -integer */ nadj = logl(pi/fabsl(t*x)); if(t=7.3159980773925781e-01) {y = 1-x; i= 0;} else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;} else {y = x; i=2;} } else { r = 0; if(x>=1.7316312789916992e+00) {y=2-x;i=0;} else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;} else {y=x-1;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*a12))))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*a13)))))); p = y*p1+p2; r += p-y/2; break; case 1: p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+ y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+ y*(t17+y*t18)))))))))))))))); r += tf + p; break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*u6)))))); p2 = 1+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*v6))))); r += p1/p2-y/2; } } /* x < 8.0 */ else if(ix<0x4002) { i = x; y = x-i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = 1+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*r7)))))); r = y/2+p/q; z = 1; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+6); /* FALLTHRU */ case 6: z *= (y+5); /* FALLTHRU */ case 5: z *= (y+4); /* FALLTHRU */ case 4: z *= (y+3); /* FALLTHRU */ case 3: z *= (y+2); /* FALLTHRU */ r += logl(z); break; } /* 8.0 <= x < 2**(p+3) */ } else if (ix<0x3fff+67) { t = logl(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*w8))))))); r = (x-half)*(t-one)+w; /* 2**(p+3) <= x <= inf */ } else r = x*(logl(x)-1); if(hx&0x8000) r = nadj - r; RETURNI(r); } diff --git a/lib/msun/ld80/e_powl.c b/lib/msun/ld80/e_powl.c index 2daf26aab93b..b028d3cb7ff2 100644 --- a/lib/msun/ld80/e_powl.c +++ b/lib/msun/ld80/e_powl.c @@ -1,658 +1,656 @@ /*- * Copyright (c) 2008 Stephen L. Moshier * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include "math_private.h" /* * Polynomial evaluator: * P[0] x^n + P[1] x^(n-1) + ... + P[n] */ static inline long double __polevll(long double x, long double *PP, int n) { long double y; long double *P; P = PP; y = *P++; do { y = y * x + *P++; } while (--n); return (y); } /* * Polynomial evaluator: * x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] */ static inline long double __p1evll(long double x, long double *PP, int n) { long double y; long double *P; P = PP; n -= 1; y = x + *P++; do { y = y * x + *P++; } while (--n); return (y); } /* powl.c * * Power function, long double precision * * * * SYNOPSIS: * * long double x, y, z, powl(); * * z = powl( x, y ); * * * * DESCRIPTION: * * Computes x raised to the yth power. Analytically, * * x**y = exp( y log(x) ). * * Following Cody and Waite, this program uses a lookup table * of 2**-i/32 and pseudo extended precision arithmetic to * obtain several extra bits of accuracy in both the logarithm * and the exponential. * * * * ACCURACY: * * The relative error of pow(x,y) can be estimated * by y dl ln(2), where dl is the absolute error of * the internally computed base 2 logarithm. At the ends * of the approximation interval the logarithm equal 1/32 * and its relative error is about 1 lsb = 1.1e-19. Hence * the predicted relative error in the result is 2.3e-21 y . * * Relative error: * arithmetic domain # trials peak rms * * IEEE +-1000 40000 2.8e-18 3.7e-19 * .001 < x < 1000, with log(x) uniformly distributed. * -1000 < y < 1000, y uniformly distributed. * * IEEE 0,8700 60000 6.5e-18 1.0e-18 * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. * * * ERROR MESSAGES: * * message condition value returned * pow overflow x**y > MAXNUM INFINITY * pow underflow x**y < 1/MAXNUM 0.0 * pow domain x<0 and y noninteger 0.0 * */ -#include #include #include #include "math_private.h" /* Table size */ #define NXT 32 /* log2(Table size) */ #define LNXT 5 /* log(1+x) = x - .5x^2 + x^3 * P(z)/Q(z) * on the domain 2^(-1/32) - 1 <= x <= 2^(1/32) - 1 */ static long double P[] = { 8.3319510773868690346226E-4L, 4.9000050881978028599627E-1L, 1.7500123722550302671919E0L, 1.4000100839971580279335E0L, }; static long double Q[] = { /* 1.0000000000000000000000E0L,*/ 5.2500282295834889175431E0L, 8.4000598057587009834666E0L, 4.2000302519914740834728E0L, }; /* A[i] = 2^(-i/32), rounded to IEEE long double precision. * If i is even, A[i] + B[i/2] gives additional accuracy. */ static long double A[33] = { 1.0000000000000000000000E0L, 9.7857206208770013448287E-1L, 9.5760328069857364691013E-1L, 9.3708381705514995065011E-1L, 9.1700404320467123175367E-1L, 8.9735453750155359320742E-1L, 8.7812608018664974155474E-1L, 8.5930964906123895780165E-1L, 8.4089641525371454301892E-1L, 8.2287773907698242225554E-1L, 8.0524516597462715409607E-1L, 7.8799042255394324325455E-1L, 7.7110541270397041179298E-1L, 7.5458221379671136985669E-1L, 7.3841307296974965571198E-1L, 7.2259040348852331001267E-1L, 7.0710678118654752438189E-1L, 6.9195494098191597746178E-1L, 6.7712777346844636413344E-1L, 6.6261832157987064729696E-1L, 6.4841977732550483296079E-1L, 6.3452547859586661129850E-1L, 6.2092890603674202431705E-1L, 6.0762367999023443907803E-1L, 5.9460355750136053334378E-1L, 5.8186242938878875689693E-1L, 5.6939431737834582684856E-1L, 5.5719337129794626814472E-1L, 5.4525386633262882960438E-1L, 5.3357020033841180906486E-1L, 5.2213689121370692017331E-1L, 5.1094857432705833910408E-1L, 5.0000000000000000000000E-1L, }; static long double B[17] = { 0.0000000000000000000000E0L, 2.6176170809902549338711E-20L, -1.0126791927256478897086E-20L, 1.3438228172316276937655E-21L, 1.2207982955417546912101E-20L, -6.3084814358060867200133E-21L, 1.3164426894366316434230E-20L, -1.8527916071632873716786E-20L, 1.8950325588932570796551E-20L, 1.5564775779538780478155E-20L, 6.0859793637556860974380E-21L, -2.0208749253662532228949E-20L, 1.4966292219224761844552E-20L, 3.3540909728056476875639E-21L, -8.6987564101742849540743E-22L, -1.2327176863327626135542E-20L, 0.0000000000000000000000E0L, }; /* 2^x = 1 + x P(x), * on the interval -1/32 <= x <= 0 */ static long double R[] = { 1.5089970579127659901157E-5L, 1.5402715328927013076125E-4L, 1.3333556028915671091390E-3L, 9.6181291046036762031786E-3L, 5.5504108664798463044015E-2L, 2.4022650695910062854352E-1L, 6.9314718055994530931447E-1L, }; #define douba(k) A[k] #define doubb(k) B[k] #define MEXP (NXT*16384.0L) /* The following if denormal numbers are supported, else -MEXP: */ #define MNEXP (-NXT*(16384.0L+64.0L)) /* log2(e) - 1 */ #define LOG2EA 0.44269504088896340735992L #define F W #define Fa Wa #define Fb Wb #define G W #define Ga Wa #define Gb u #define H W #define Ha Wb #define Hb Wb static const long double MAXLOGL = 1.1356523406294143949492E4L; static const long double MINLOGL = -1.13994985314888605586758E4L; static const long double LOGE2L = 6.9314718055994530941723E-1L; static volatile long double z; static long double w, W, Wa, Wb, ya, yb, u; static const long double huge = 0x1p10000L; #if 0 /* XXX Prevent gcc from erroneously constant folding this. */ static const long double twom10000 = 0x1p-10000L; #else static volatile long double twom10000 = 0x1p-10000L; #endif static long double reducl( long double ); static long double powil ( long double, int ); long double powl(long double x, long double y) { /* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */ int i, nflg, iyflg, yoddint; long e; if( y == 0.0L ) return( 1.0L ); if( x == 1.0L ) return( 1.0L ); if( isnan(x) ) return ( nan_mix(x, y) ); if( isnan(y) ) return ( nan_mix(x, y) ); if( y == 1.0L ) return( x ); if( !isfinite(y) && x == -1.0L ) return( 1.0L ); if( y >= LDBL_MAX ) { if( x > 1.0L ) return( INFINITY ); if( x > 0.0L && x < 1.0L ) return( 0.0L ); if( x < -1.0L ) return( INFINITY ); if( x > -1.0L && x < 0.0L ) return( 0.0L ); } if( y <= -LDBL_MAX ) { if( x > 1.0L ) return( 0.0L ); if( x > 0.0L && x < 1.0L ) return( INFINITY ); if( x < -1.0L ) return( 0.0L ); if( x > -1.0L && x < 0.0L ) return( INFINITY ); } if( x >= LDBL_MAX ) { if( y > 0.0L ) return( INFINITY ); return( 0.0L ); } w = floorl(y); /* Set iyflg to 1 if y is an integer. */ iyflg = 0; if( w == y ) iyflg = 1; /* Test for odd integer y. */ yoddint = 0; if( iyflg ) { ya = fabsl(y); ya = floorl(0.5L * ya); yb = 0.5L * fabsl(w); if( ya != yb ) yoddint = 1; } if( x <= -LDBL_MAX ) { if( y > 0.0L ) { if( yoddint ) return( -INFINITY ); return( INFINITY ); } if( y < 0.0L ) { if( yoddint ) return( -0.0L ); return( 0.0 ); } } nflg = 0; /* flag = 1 if x<0 raised to integer power */ if( x <= 0.0L ) { if( x == 0.0L ) { if( y < 0.0 ) { if( signbit(x) && yoddint ) return( -INFINITY ); return( INFINITY ); } if( y > 0.0 ) { if( signbit(x) && yoddint ) return( -0.0L ); return( 0.0 ); } if( y == 0.0L ) return( 1.0L ); /* 0**0 */ else return( 0.0L ); /* 0**y */ } else { if( iyflg == 0 ) return (x - x) / (x - x); /* (x<0)**(non-int) is NaN */ nflg = 1; } } /* Integer power of an integer. */ if( iyflg ) { i = w; w = floorl(x); if( (w == x) && (fabsl(y) < 32768.0) ) { w = powil( x, (int) y ); return( w ); } } if( nflg ) x = fabsl(x); /* separate significand from exponent */ x = frexpl( x, &i ); e = i; /* find significand in antilog table A[] */ i = 1; if( x <= douba(17) ) i = 17; if( x <= douba(i+8) ) i += 8; if( x <= douba(i+4) ) i += 4; if( x <= douba(i+2) ) i += 2; if( x >= douba(1) ) i = -1; i += 1; /* Find (x - A[i])/A[i] * in order to compute log(x/A[i]): * * log(x) = log( a x/a ) = log(a) + log(x/a) * * log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a */ x -= douba(i); x -= doubb(i/2); x /= douba(i); /* rational approximation for log(1+v): * * log(1+v) = v - v**2/2 + v**3 P(v) / Q(v) */ z = x*x; w = x * ( z * __polevll( x, P, 3 ) / __p1evll( x, Q, 3 ) ); w = w - ldexpl( z, -1 ); /* w - 0.5 * z */ /* Convert to base 2 logarithm: * multiply by log2(e) = 1 + LOG2EA */ z = LOG2EA * w; z += w; z += LOG2EA * x; z += x; /* Compute exponent term of the base 2 logarithm. */ w = -i; w = ldexpl( w, -LNXT ); /* divide by NXT */ w += e; /* Now base 2 log of x is w + z. */ /* Multiply base 2 log by y, in extended precision. */ /* separate y into large part ya * and small part yb less than 1/NXT */ ya = reducl(y); yb = y - ya; /* (w+z)(ya+yb) * = w*ya + w*yb + z*y */ F = z * y + w * yb; Fa = reducl(F); Fb = F - Fa; G = Fa + w * ya; Ga = reducl(G); Gb = G - Ga; H = Fb + Gb; Ha = reducl(H); w = ldexpl( Ga+Ha, LNXT ); /* Test the power of 2 for overflow */ if( w > MEXP ) return (huge * huge); /* overflow */ if( w < MNEXP ) return (twom10000 * twom10000); /* underflow */ e = w; Hb = H - Ha; if( Hb > 0.0L ) { e += 1; Hb -= (1.0L/NXT); /*0.0625L;*/ } /* Now the product y * log2(x) = Hb + e/NXT. * * Compute base 2 exponential of Hb, * where -0.0625 <= Hb <= 0. */ z = Hb * __polevll( Hb, R, 6 ); /* z = 2**Hb - 1 */ /* Express e/NXT as an integer plus a negative number of (1/NXT)ths. * Find lookup table entry for the fractional power of 2. */ if( e < 0 ) i = 0; else i = 1; i = e/NXT + i; e = NXT*i - e; w = douba( e ); z = w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */ z = z + w; z = ldexpl( z, i ); /* multiply by integer power of 2 */ if( nflg ) { /* For negative x, * find out if the integer exponent * is odd or even. */ w = ldexpl( y, -1 ); w = floorl(w); w = ldexpl( w, 1 ); if( w != y ) z = -z; /* odd exponent */ } return( z ); } /* Find a multiple of 1/NXT that is within 1/NXT of x. */ static inline long double reducl(long double x) { long double t; t = ldexpl( x, LNXT ); t = floorl( t ); t = ldexpl( t, -LNXT ); return(t); } /* powil.c * * Real raised to integer power, long double precision * * * * SYNOPSIS: * * long double x, y, powil(); * int n; * * y = powil( x, n ); * * * * DESCRIPTION: * * Returns argument x raised to the nth power. * The routine efficiently decomposes n as a sum of powers of * two. The desired power is a product of two-to-the-kth * powers of x. Thus to compute the 32767 power of x requires * 28 multiplications instead of 32767 multiplications. * * * * ACCURACY: * * * Relative error: * arithmetic x domain n domain # trials peak rms * IEEE .001,1000 -1022,1023 50000 4.3e-17 7.8e-18 * IEEE 1,2 -1022,1023 20000 3.9e-17 7.6e-18 * IEEE .99,1.01 0,8700 10000 3.6e-16 7.2e-17 * * Returns MAXNUM on overflow, zero on underflow. * */ static long double powil(long double x, int nn) { long double ww, y; long double s; int n, e, sign, asign, lx; if( x == 0.0L ) { if( nn == 0 ) return( 1.0L ); else if( nn < 0 ) return( LDBL_MAX ); else return( 0.0L ); } if( nn == 0 ) return( 1.0L ); if( x < 0.0L ) { asign = -1; x = -x; } else asign = 0; if( nn < 0 ) { sign = -1; n = -nn; } else { sign = 1; n = nn; } /* Overflow detection */ /* Calculate approximate logarithm of answer */ s = x; s = frexpl( s, &lx ); e = (lx - 1)*n; if( (e == 0) || (e > 64) || (e < -64) ) { s = (s - 7.0710678118654752e-1L) / (s + 7.0710678118654752e-1L); s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L; } else { s = LOGE2L * e; } if( s > MAXLOGL ) return (huge * huge); /* overflow */ if( s < MINLOGL ) return (twom10000 * twom10000); /* underflow */ /* Handle tiny denormal answer, but with less accuracy * since roundoff error in 1.0/x will be amplified. * The precise demarcation should be the gradual underflow threshold. */ if( s < (-MAXLOGL+2.0L) ) { x = 1.0L/x; sign = -sign; } /* First bit of the power */ if( n & 1 ) y = x; else { y = 1.0L; asign = 0; } ww = x; n >>= 1; while( n ) { ww = ww * ww; /* arg to the 2-to-the-kth power */ if( n & 1 ) /* if that bit is set, then include in product */ y *= ww; n >>= 1; } if( asign ) y = -y; /* odd power of negative number */ if( sign < 0 ) y = 1.0L/y; return(y); } diff --git a/lib/msun/ld80/e_rem_pio2l.h b/lib/msun/ld80/e_rem_pio2l.h index d9e4d3a0941f..88412c3d0cf9 100644 --- a/lib/msun/ld80/e_rem_pio2l.h +++ b/lib/msun/ld80/e_rem_pio2l.h @@ -1,141 +1,140 @@ /* From: @(#)e_rem_pio2.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * Optimized by Bruce D. Evans. */ -#include /* ld80 version of __ieee754_rem_pio2l(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __kernel_rem_pio2() */ #include #include "math.h" #include "math_private.h" #include "fpmath.h" #define BIAS (LDBL_MAX_EXP - 1) /* * invpio2: 64 bits of 2/pi * pio2_1: first 39 bits of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 39 bits of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 39 bits of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */ pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */ pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */ #if defined(__amd64__) || defined(__i386__) /* Long double constants are slow on these arches, and broken on i386. */ static const volatile double invpio2hi = 6.3661977236758138e-01, /* 0x145f306dc9c883.0p-53 */ invpio2lo = -3.9356538861223811e-17, /* -0x16b00000000000.0p-107 */ pio2_1thi = -1.0746346554971943e-12, /* -0x12e7b9676733af.0p-92 */ pio2_1tlo = 8.8451028997905949e-29, /* 0x1c080000000000.0p-146 */ pio2_2thi = 6.3683171635109499e-25, /* 0x18a2e03707344a.0p-133 */ pio2_2tlo = 2.3183081793789774e-41, /* 0x10280000000000.0p-187 */ pio2_3thi = -2.7529965190440717e-37, /* -0x176b7ed8fbbacc.0p-174 */ pio2_3tlo = -4.2006647512740502e-54; /* -0x19c00000000000.0p-230 */ #define invpio2 ((long double)invpio2hi + invpio2lo) #define pio2_1t ((long double)pio2_1thi + pio2_1tlo) #define pio2_2t ((long double)pio2_2thi + pio2_2tlo) #define pio2_3t ((long double)pio2_3thi + pio2_3tlo) #else static const long double invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */ pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */ pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */ #endif static inline __always_inline int __ieee754_rem_pio2l(long double x, long double *y) { union IEEEl2bits u,u1; long double z,w,t,r,fn; double tx[3],ty[2]; int e0,ex,i,j,nx,n; int16_t expsign; u.e = x; expsign = u.xbits.expsign; ex = expsign & 0x7fff; if (ex < BIAS + 25 || (ex == BIAS + 25 && u.bits.manh < 0xc90fdaa2)) { /* |x| ~< 2^25*(pi/2), medium size */ fn = rnintl(x*invpio2); n = irint(fn); r = x-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 102 bit */ { union IEEEl2bits u2; int ex1; j = ex; y[0] = r-w; u2.e = y[0]; ex1 = u2.xbits.expsign & 0x7fff; i = j-ex1; if(i>22) { /* 2nd iteration needed, good to 141 */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; u2.e = y[0]; ex1 = u2.xbits.expsign & 0x7fff; i = j-ex1; if(i>61) { /* 3rd iteration need, 180 bits acc */ t = r; /* will cover all possible cases */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); y[0] = r-w; } } } y[1] = (r-y[0])-w; return n; } /* * all other (large) arguments */ if(ex==0x7fff) { /* x is inf or NaN */ y[0]=y[1]=x-x; return 0; } /* set z = scalbn(|x|,ilogb(x)-23) */ u1.e = x; e0 = ex - BIAS - 23; /* e0 = ilogb(|x|)-23; */ u1.xbits.expsign = ex - e0; z = u1.e; for(i=0;i<2;i++) { tx[i] = (double)((int32_t)(z)); z = (z-tx[i])*two24; } tx[2] = z; nx = 3; while(tx[nx-1]==zero) nx--; /* skip zero term */ n = __kernel_rem_pio2(tx,ty,e0,nx,2); r = (long double)ty[0] + ty[1]; w = ty[1] - (r - ty[0]); if(expsign<0) {y[0] = -r; y[1] = -w; return -n;} y[0] = r; y[1] = w; return n; } diff --git a/lib/msun/ld80/invtrig.c b/lib/msun/ld80/invtrig.c index 0e2d49546391..76eb681454d3 100644 --- a/lib/msun/ld80/invtrig.c +++ b/lib/msun/ld80/invtrig.c @@ -1,82 +1,81 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include "invtrig.h" /* * asinl() and acosl() */ const long double pS0 = 1.66666666666666666631e-01L, pS1 = -4.16313987993683104320e-01L, pS2 = 3.69068046323246813704e-01L, pS3 = -1.36213932016738603108e-01L, pS4 = 1.78324189708471965733e-02L, pS5 = -2.19216428382605211588e-04L, pS6 = -7.10526623669075243183e-06L, qS1 = -2.94788392796209867269e+00L, qS2 = 3.27309890266528636716e+00L, qS3 = -1.68285799854822427013e+00L, qS4 = 3.90699412641738801874e-01L, qS5 = -3.14365703596053263322e-02L; /* * atanl() */ const long double atanhi[] = { 4.63647609000806116202e-01L, 7.85398163397448309628e-01L, 9.82793723247329067960e-01L, 1.57079632679489661926e+00L, }; const long double atanlo[] = { 1.18469937025062860669e-20L, -1.25413940316708300586e-20L, 2.55232234165405176172e-20L, -2.50827880633416601173e-20L, }; const long double aT[] = { 3.33333333333333333017e-01L, -1.99999999999999632011e-01L, 1.42857142857046531280e-01L, -1.11111111100562372733e-01L, 9.09090902935647302252e-02L, -7.69230552476207730353e-02L, 6.66661718042406260546e-02L, -5.88158892835030888692e-02L, 5.25499891539726639379e-02L, -4.70119845393155721494e-02L, 4.03539201366454414072e-02L, -2.91303858419364158725e-02L, 1.24822046299269234080e-02L, }; const long double pi_lo = -5.01655761266833202345e-20L; diff --git a/lib/msun/ld80/k_cosl.c b/lib/msun/ld80/k_cosl.c index e76d429b90ef..b4bcf6fe38f3 100644 --- a/lib/msun/ld80/k_cosl.c +++ b/lib/msun/ld80/k_cosl.c @@ -1,76 +1,75 @@ /* From: @(#)k_cos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld80 version of k_cos.c. See ../src/k_cos.c for most comments. */ #include "math_private.h" /* * Domain [-0.7854, 0.7854], range ~[-2.43e-23, 2.425e-23]: * |cos(x) - c(x)| < 2**-75.1 * * The coefficients of c(x) were generated by a pari-gp script using * a Remez algorithm that searches for the best higher coefficients * after rounding leading coefficients to a specified precision. * * Simpler methods like Chebyshev or basic Remez barely suffice for * cos() in 64-bit precision, because we want the coefficient of x^2 * to be precisely -0.5 so that multiplying by it is exact, and plain * rounding of the coefficients of a good polynomial approximation only * gives this up to about 64-bit precision. Plain rounding also gives * a mediocre approximation for the coefficient of x^4, but a rounding * error of 0.5 ulps for this coefficient would only contribute ~0.01 * ulps to the final error, so this is unimportant. Rounding errors in * higher coefficients are even less important. * * In fact, coefficients above the x^4 one only need to have 53-bit * precision, and this is more efficient. We get this optimization * almost for free from the complications needed to search for the best * higher coefficients. */ static const double one = 1.0; #if defined(__amd64__) || defined(__i386__) /* Long double constants are slow on these arches, and broken on i386. */ static const volatile double C1hi = 0.041666666666666664, /* 0x15555555555555.0p-57 */ C1lo = 2.2598839032744733e-18; /* 0x14d80000000000.0p-111 */ #define C1 ((long double)C1hi + C1lo) #else static const long double C1 = 0.0416666666666666666136L; /* 0xaaaaaaaaaaaaaa9b.0p-68 */ #endif static const double C2 = -0.0013888888888888874, /* -0x16c16c16c16c10.0p-62 */ C3 = 0.000024801587301571716, /* 0x1a01a01a018e22.0p-68 */ C4 = -0.00000027557319215507120, /* -0x127e4fb7602f22.0p-74 */ C5 = 0.0000000020876754400407278, /* 0x11eed8caaeccf1.0p-81 */ C6 = -1.1470297442401303e-11, /* -0x19393412bd1529.0p-89 */ C7 = 4.7383039476436467e-14; /* 0x1aac9d9af5c43e.0p-97 */ long double __kernel_cosl(long double x, long double y) { long double hz,z,r,w; z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7)))))); hz = 0.5*z; w = one-hz; return w + (((one-w)-hz) + (z*r-x*y)); } diff --git a/lib/msun/ld80/k_expl.h b/lib/msun/ld80/k_expl.h index 8c3617e4b177..fabf5a792205 100644 --- a/lib/msun/ld80/k_expl.h +++ b/lib/msun/ld80/k_expl.h @@ -1,299 +1,298 @@ /* from: FreeBSD: head/lib/msun/ld80/s_expl.c 251343 2013-06-03 19:51:32Z kargl */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009-2013 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Optimized by Bruce D. Evans. */ -#include /* * See s_expl.c for more comments about __k_expl(). * * See ../src/e_exp.c and ../src/k_exp.h for precision-independent comments * about the secondary kernels. */ #define INTERVALS 128 #define LOG2_INTERVALS 7 #define BIAS (LDBL_MAX_EXP - 1) static const double /* * ln2/INTERVALS = L1+L2 (hi+lo decomposition for multiplication). L1 must * have at least 22 (= log2(|LDBL_MIN_EXP-extras|) + log2(INTERVALS)) lowest * bits zero so that multiplication of it by n is exact. */ INV_L = 1.8466496523378731e+2, /* 0x171547652b82fe.0p-45 */ L1 = 5.4152123484527692e-3, /* 0x162e42ff000000.0p-60 */ L2 = -3.2819649005320973e-13, /* -0x1718432a1b0e26.0p-94 */ /* * Domain [-0.002708, 0.002708], range ~[-5.7136e-24, 5.7110e-24]: * |exp(x) - p(x)| < 2**-77.2 * (0.002708 is ln2/(2*INTERVALS) rounded up a little). */ A2 = 0.5, A3 = 1.6666666666666119e-1, /* 0x15555555555490.0p-55 */ A4 = 4.1666666666665887e-2, /* 0x155555555554e5.0p-57 */ A5 = 8.3333354987869413e-3, /* 0x1111115b789919.0p-59 */ A6 = 1.3888891738560272e-3; /* 0x16c16c651633ae.0p-62 */ /* * 2^(i/INTERVALS) for i in [0,INTERVALS] is represented by two values where * the first 53 bits of the significand are stored in hi and the next 53 * bits are in lo. Tang's paper states that the trailing 6 bits of hi must * be zero for his algorithm in both single and double precision, because * the table is re-used in the implementation of expm1() where a floating * point addition involving hi must be exact. Here hi is double, so * converting it to long double gives 11 trailing zero bits. */ static const struct { double hi; double lo; } tbl[INTERVALS] = { { 0x1p+0, 0x0p+0 }, /* * XXX hi is rounded down, and the formatting is not quite normal. * But I rather like both. The 0x1.*p format is good for 4N+1 * mantissa bits. Rounding down makes the lo terms positive, * so that the columnar formatting can be simpler. */ { 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54 }, { 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53 }, { 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53 }, { 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55 }, { 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53 }, { 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57 }, { 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54 }, { 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54 }, { 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54 }, { 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59 }, { 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53 }, { 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53 }, { 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53 }, { 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53 }, { 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55 }, { 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53 }, { 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53 }, { 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55 }, { 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53 }, { 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54 }, { 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53 }, { 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55 }, { 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55 }, { 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54 }, { 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55 }, { 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55 }, { 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53 }, { 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55 }, { 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53 }, { 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54 }, { 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56 }, { 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55 }, { 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55 }, { 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54 }, { 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53 }, { 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53 }, { 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53 }, { 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53 }, { 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53 }, { 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55 }, { 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53 }, { 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53 }, { 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53 }, { 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59 }, { 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54 }, { 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56 }, { 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54 }, { 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56 }, { 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54 }, { 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53 }, { 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53 }, { 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53 }, { 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53 }, { 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54 }, { 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55 }, { 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54 }, { 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60 }, { 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54 }, { 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53 }, { 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53 }, { 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53 }, { 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53 }, { 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57 }, { 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53 }, { 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53 }, { 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53 }, { 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53 }, { 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53 }, { 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53 }, { 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53 }, { 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54 }, { 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53 }, { 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54 }, { 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56 }, { 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53 }, { 0x1.82589994cce12p+0, 0x1.159f115f56694p-53 }, { 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53 }, { 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53 }, { 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54 }, { 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54 }, { 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53 }, { 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55 }, { 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53 }, { 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53 }, { 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53 }, { 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53 }, { 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53 }, { 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56 }, { 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56 }, { 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53 }, { 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54 }, { 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53 }, { 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54 }, { 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54 }, { 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53 }, { 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54 }, { 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53 }, { 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53 }, { 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53 }, { 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53 }, { 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53 }, { 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55 }, { 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53 }, { 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55 }, { 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54 }, { 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54 }, { 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56 }, { 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56 }, { 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53 }, { 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53 }, { 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53 }, { 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55 }, { 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53 }, { 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54 }, { 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54 }, { 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53 }, { 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53 }, { 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55 }, { 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54 }, { 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53 }, { 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53 }, { 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54 }, { 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54 }, { 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54 }, { 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53 }, { 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55 }, { 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 } }; /* * Kernel for expl(x). x must be finite and not tiny or huge. * "tiny" is anything that would make us underflow (|A6*x^6| < ~LDBL_MIN). * "huge" is anything that would make fn*L1 inexact (|x| > ~2**17*ln2). */ static inline void __k_expl(long double x, long double *hip, long double *lop, int *kp) { long double fn, q, r, r1, r2, t, z; int n, n2; /* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */ fn = rnintl(x * INV_L); r = x - fn * L1 - fn * L2; /* r = r1 + r2 done independently. */ n = irint(fn); n2 = (unsigned)n % INTERVALS; /* Depend on the sign bit being propagated: */ *kp = n >> LOG2_INTERVALS; r1 = x - fn * L1; r2 = fn * -L2; /* Evaluate expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */ z = r * r; #if 0 q = r2 + z * (A2 + r * A3) + z * z * (A4 + r * A5) + z * z * z * A6; #else q = r2 + z * A2 + z * r * (A3 + r * A4 + z * (A5 + r * A6)); #endif t = (long double)tbl[n2].lo + tbl[n2].hi; *hip = tbl[n2].hi; *lop = tbl[n2].lo + t * (q + r1); } static inline void k_hexpl(long double x, long double *hip, long double *lop) { float twopkm1; int k; __k_expl(x, hip, lop, &k); SET_FLOAT_WORD(twopkm1, 0x3f800000 + ((k - 1) << 23)); *hip *= twopkm1; *lop *= twopkm1; } static inline long double hexpl(long double x) { long double hi, lo, twopkm2; int k; twopkm2 = 1; __k_expl(x, &hi, &lo, &k); SET_LDBL_EXPSIGN(twopkm2, BIAS + k - 2); return (lo + hi) * 2 * twopkm2; } #ifdef _COMPLEX_H /* * See ../src/k_exp.c for details. */ static inline long double complex __ldexp_cexpl(long double complex z, int expt) { long double c, exp_x, hi, lo, s; long double x, y, scale1, scale2; int half_expt, k; x = creall(z); y = cimagl(z); __k_expl(x, &hi, &lo, &k); exp_x = (lo + hi) * 0x1p16382L; expt += k - 16382; scale1 = 1; half_expt = expt / 2; SET_LDBL_EXPSIGN(scale1, BIAS + half_expt); scale2 = 1; SET_LDBL_EXPSIGN(scale2, BIAS + expt - half_expt); sincosl(y, &s, &c); return (CMPLXL(c * exp_x * scale1 * scale2, s * exp_x * scale1 * scale2)); } #endif /* _COMPLEX_H */ diff --git a/lib/msun/ld80/k_sinl.c b/lib/msun/ld80/k_sinl.c index 21c1946b5e1b..b9a7fbe7c698 100644 --- a/lib/msun/ld80/k_sinl.c +++ b/lib/msun/ld80/k_sinl.c @@ -1,60 +1,59 @@ /* From: @(#)k_sin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld80 version of k_sin.c. See ../src/k_sin.c for most comments. */ #include "math_private.h" static const double half = 0.5; /* * Domain [-0.7854, 0.7854], range ~[-1.89e-22, 1.915e-22] * |sin(x)/x - s(x)| < 2**-72.1 * * See ../ld80/k_cosl.c for more details about the polynomial. */ #if defined(__amd64__) || defined(__i386__) /* Long double constants are slow on these arches, and broken on i386. */ static const volatile double S1hi = -0.16666666666666666, /* -0x15555555555555.0p-55 */ S1lo = -9.2563760475949941e-18; /* -0x15580000000000.0p-109 */ #define S1 ((long double)S1hi + S1lo) #else static const long double S1 = -0.166666666666666666671L; /* -0xaaaaaaaaaaaaaaab.0p-66 */ #endif static const double S2 = 0.0083333333333333332, /* 0x11111111111111.0p-59 */ S3 = -0.00019841269841269427, /* -0x1a01a01a019f81.0p-65 */ S4 = 0.0000027557319223597490, /* 0x171de3a55560f7.0p-71 */ S5 = -0.000000025052108218074604, /* -0x1ae64564f16cad.0p-78 */ S6 = 1.6059006598854211e-10, /* 0x161242b90243b5.0p-85 */ S7 = -7.6429779983024564e-13, /* -0x1ae42ebd1b2e00.0p-93 */ S8 = 2.6174587166648325e-15; /* 0x179372ea0b3f64.0p-101 */ long double __kernel_sinl(long double x, long double y, int iy) { long double z,r,v; z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8))))); if(iy==0) return x+v*(S1+z*r); else return x-((z*(half*y-v*r)-y)-v*S1); } diff --git a/lib/msun/ld80/k_tanl.c b/lib/msun/ld80/k_tanl.c index 4965c669979f..07d13608a5f6 100644 --- a/lib/msun/ld80/k_tanl.c +++ b/lib/msun/ld80/k_tanl.c @@ -1,122 +1,121 @@ /* From: @(#)k_tan.c 1.5 04/04/22 SMI */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ld80 version of k_tan.c. See ../src/k_tan.c for most comments. */ #include "math.h" #include "math_private.h" /* * Domain [-0.67434, 0.67434], range ~[-2.25e-22, 1.921e-22] * |tan(x)/x - t(x)| < 2**-71.9 * * See k_cosl.c for more details about the polynomial. */ #if defined(__amd64__) || defined(__i386__) /* Long double constants are slow on these arches, and broken on i386. */ static const volatile double T3hi = 0.33333333333333331, /* 0x15555555555555.0p-54 */ T3lo = 1.8350121769317163e-17, /* 0x15280000000000.0p-108 */ T5hi = 0.13333333333333336, /* 0x11111111111112.0p-55 */ T5lo = 1.3051083651294260e-17, /* 0x1e180000000000.0p-109 */ T7hi = 0.053968253968250494, /* 0x1ba1ba1ba1b827.0p-57 */ T7lo = 3.1509625637859973e-18, /* 0x1d100000000000.0p-111 */ pio4_hi = 0.78539816339744828, /* 0x1921fb54442d18.0p-53 */ pio4_lo = 3.0628711372715500e-17, /* 0x11a80000000000.0p-107 */ pio4lo_hi = -1.2541394031670831e-20, /* -0x1d9cceba3f91f2.0p-119 */ pio4lo_lo = 6.1493048227390915e-37; /* 0x1a280000000000.0p-173 */ #define T3 ((long double)T3hi + T3lo) #define T5 ((long double)T5hi + T5lo) #define T7 ((long double)T7hi + T7lo) #define pio4 ((long double)pio4_hi + pio4_lo) #define pio4lo ((long double)pio4lo_hi + pio4lo_lo) #else static const long double T3 = 0.333333333333333333180L, /* 0xaaaaaaaaaaaaaaa5.0p-65 */ T5 = 0.133333333333333372290L, /* 0x88888888888893c3.0p-66 */ T7 = 0.0539682539682504975744L, /* 0xdd0dd0dd0dc13ba2.0p-68 */ pio4 = 0.785398163397448309628L, /* 0xc90fdaa22168c235.0p-64 */ pio4lo = -1.25413940316708300586e-20L; /* -0xece675d1fc8f8cbb.0p-130 */ #endif static const double T9 = 0.021869488536312216, /* 0x1664f4882cc1c2.0p-58 */ T11 = 0.0088632355256619590, /* 0x1226e355c17612.0p-59 */ T13 = 0.0035921281113786528, /* 0x1d6d3d185d7ff8.0p-61 */ T15 = 0.0014558334756312418, /* 0x17da354aa3f96b.0p-62 */ T17 = 0.00059003538700862256, /* 0x13559358685b83.0p-63 */ T19 = 0.00023907843576635544, /* 0x1f56242026b5be.0p-65 */ T21 = 0.000097154625656538905, /* 0x1977efc26806f4.0p-66 */ T23 = 0.000038440165747303162, /* 0x14275a09b3ceac.0p-67 */ T25 = 0.000018082171885432524, /* 0x12f5e563e5487e.0p-68 */ T27 = 0.0000024196006108814377, /* 0x144c0d80cc6896.0p-71 */ T29 = 0.0000078293456938132840, /* 0x106b59141a6cb3.0p-69 */ T31 = -0.0000032609076735050182, /* -0x1b5abef3ba4b59.0p-71 */ T33 = 0.0000023261313142559411; /* 0x13835436c0c87f.0p-71 */ long double __kernel_tanl(long double x, long double y, int iy) { long double z, r, v, w, s; long double osign; int i; iy = (iy == 1 ? -1 : 1); /* XXX recover original interface */ osign = (x >= 0 ? 1.0 : -1.0); /* XXX slow, probably wrong for -0 */ if (fabsl(x) >= 0.67434) { if (x < 0) { x = -x; y = -y; } z = pio4 - x; w = pio4lo - y; x = z + w; y = 0.0; i = 1; } else i = 0; z = x * x; w = z * z; r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 + w * (T25 + w * (T29 + w * T33)))))); v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 + w * (T27 + w * T31)))))); s = z * x; r = y + z * (s * (r + v) + y); r += T3 * s; w = x + r; if (i == 1) { v = (long double) iy; return osign * (v - 2.0 * (x - (w * w / (w + v) - r))); } if (iy == 1) return w; else { /* * if allow error up to 2 ulp, simply return * -1.0 / (x+r) here */ /* compute -1.0 / (x+r) accurately */ long double a, t; z = w; z = z + 0x1p32 - 0x1p32; v = r - (z - x); /* z+v = r+x */ t = a = -1.0 / w; /* a = -1.0/w */ t = t + 0x1p32 - 0x1p32; s = 1.0 + t * z; return t + a * (s + t * v); } } diff --git a/lib/msun/ld80/s_cexpl.c b/lib/msun/ld80/s_cexpl.c index 81a4d727561b..cbe9dcd64099 100644 --- a/lib/msun/ld80/s_cexpl.c +++ b/lib/msun/ld80/s_cexpl.c @@ -1,105 +1,104 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * src/s_cexp.c converted to long double complex by Steven G. Kargl */ -#include #include #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #include "k_expl.h" long double complex cexpl (long double complex z) { long double c, exp_x, s, x, y; uint64_t lx, ly; uint16_t hx, hy; ENTERI(); x = creall(z); y = cimagl(z); EXTRACT_LDBL80_WORDS(hy, ly, y); hy &= 0x7fff; /* cexp(x + I 0) = exp(x) + I 0 */ if ((hy | ly) == 0) RETURNI(CMPLXL(expl(x), y)); EXTRACT_LDBL80_WORDS(hx, lx, x); /* cexp(0 + I y) = cos(y) + I sin(y) */ if (((hx & 0x7fff) | lx) == 0) { sincosl(y, &s, &c); RETURNI(CMPLXL(c, s)); } if (hy >= 0x7fff) { if ((hx & 0x7fff) < 0x7fff || ((hx & 0x7fff) == 0x7fff && (lx & 0x7fffffffffffffffULL) != 0)) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ RETURNI(CMPLXL(y - y, y - y)); } else if (hx & 0x8000) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ RETURNI(CMPLXL(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ RETURNI(CMPLXL(x, y - y)); } } /* * exp_ovfl = 11356.5234062941439497 * cexp_ovfl = 22755.3287906024445633 */ if ((hx == 0x400c && lx > 0xb17217f7d1cf79acULL) || (hx == 0x400d && lx < 0xb1c6a8573de9768cULL)) { /* * x is between exp_ovfl and cexp_ovfl, so we must scale to * avoid overflow in exp(x). */ RETURNI(__ldexp_cexpl(z, 0)); } else { /* * Cases covered here: * - x < exp_ovfl and exp(x) won't overflow (common case) * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 * - x = +-Inf (generated by exp()) * - x = NaN (spurious inexact exception from y) */ exp_x = expl(x); sincosl(y, &s, &c); RETURNI(CMPLXL(exp_x * c, exp_x * s)); } } diff --git a/lib/msun/ld80/s_erfl.c b/lib/msun/ld80/s_erfl.c index 362b4f07d6bc..13b7d11e09ea 100644 --- a/lib/msun/ld80/s_erfl.c +++ b/lib/msun/ld80/s_erfl.c @@ -1,335 +1,334 @@ /* @(#)s_erf.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See s_erf.c for complete comments. * * Converted to long double by Steven G. Kargl. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" /* XXX Prevent compilers from erroneously constant folding: */ static const volatile long double tiny = 0x1p-10000L; static const double half= 0.5, one = 1, two = 2; /* * In the domain [0, 2**-34], only the first term in the power series * expansion of erf(x) is used. The magnitude of the first neglected * terms is less than 2**-102. */ static const union IEEEl2bits efxu = LD80C(0x8375d410a6db446c, -3, 1.28379167095512573902e-1L), efx8u = LD80C(0x8375d410a6db446c, 0, 1.02703333676410059122e+0L), /* * Domain [0, 0.84375], range ~[-1.423e-22, 1.423e-22]: * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-72.573 */ pp0u = LD80C(0x8375d410a6db446c, -3, 1.28379167095512573902e-1L), pp1u = LD80C(0xa46c7d09ec3d0cec, -2, -3.21140201054840180596e-1L), pp2u = LD80C(0x9b31e66325576f86, -5, -3.78893851760347812082e-2L), pp3u = LD80C(0x804ac72c9a0b97dd, -7, -7.83032847030604679616e-3L), pp4u = LD80C(0x9f42bcbc3d5a601d, -12, -3.03765663857082048459e-4L), pp5u = LD80C(0x9ec4ad6193470693, -16, -1.89266527398167917502e-5L), qq1u = LD80C(0xdb4b8eb713188d6b, -2, 4.28310832832310510579e-1L), qq2u = LD80C(0xa5750835b2459bd1, -4, 8.07896272074540216658e-2L), qq3u = LD80C(0x8b85d6bd6a90b51c, -7, 8.51579638189385354266e-3L), qq4u = LD80C(0x87332f82cff4ff96, -11, 5.15746855583604912827e-4L), qq5u = LD80C(0x83466cb6bf9dca00, -16, 1.56492109706256700009e-5L), qq6u = LD80C(0xf5bf98c2f996bf63, -24, 1.14435527803073879724e-7L); #define efx (efxu.e) #define efx8 (efx8u.e) #define pp0 (pp0u.e) #define pp1 (pp1u.e) #define pp2 (pp2u.e) #define pp3 (pp3u.e) #define pp4 (pp4u.e) #define pp5 (pp5u.e) #define qq1 (qq1u.e) #define qq2 (qq2u.e) #define qq3 (qq3u.e) #define qq4 (qq4u.e) #define qq5 (qq5u.e) #define qq6 (qq6u.e) static const union IEEEl2bits erxu = LD80C(0xd7bb3d0000000000, -1, 8.42700779438018798828e-1L), /* * Domain [0.84375, 1.25], range ~[-8.132e-22, 8.113e-22]: * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-71.762 */ pa0u = LD80C(0xe8211158da02c692, -27, 1.35116960705131296711e-8L), pa1u = LD80C(0xd488f89f36988618, -2, 4.15107507167065612570e-1L), pa2u = LD80C(0xece74f8c63fa3942, -4, -1.15675565215949226989e-1L), pa3u = LD80C(0xc8d31e020727c006, -4, 9.80589241379624665791e-2L), pa4u = LD80C(0x985d5d5fafb0551f, -5, 3.71984145558422368847e-2L), pa5u = LD80C(0xa5b6c4854d2f5452, -8, -5.05718799340957673661e-3L), pa6u = LD80C(0x85c8d58fe3993a47, -8, 4.08277919612202243721e-3L), pa7u = LD80C(0xddbfbc23677b35cf, -13, 2.11476292145347530794e-4L), qa1u = LD80C(0xb8a977896f5eff3f, -1, 7.21335860303380361298e-1L), qa2u = LD80C(0x9fcd662c3d4eac86, -1, 6.24227891731886593333e-1L), qa3u = LD80C(0x9d0b618eac67ba07, -2, 3.06727455774491855801e-1L), qa4u = LD80C(0x881a4293f6d6c92d, -3, 1.32912674218195890535e-1L), qa5u = LD80C(0xbab144f07dea45bf, -5, 4.55792134233613027584e-2L), qa6u = LD80C(0xa6c34ba438bdc900, -7, 1.01783980070527682680e-2L), qa7u = LD80C(0x8fa866dc20717a91, -9, 2.19204436518951438183e-3L); #define erx (erxu.e) #define pa0 (pa0u.e) #define pa1 (pa1u.e) #define pa2 (pa2u.e) #define pa3 (pa3u.e) #define pa4 (pa4u.e) #define pa5 (pa5u.e) #define pa6 (pa6u.e) #define pa7 (pa7u.e) #define qa1 (qa1u.e) #define qa2 (qa2u.e) #define qa3 (qa3u.e) #define qa4 (qa4u.e) #define qa5 (qa5u.e) #define qa6 (qa6u.e) #define qa7 (qa7u.e) static const union IEEEl2bits /* * Domain [1.25,2.85715], range ~[-2.334e-22,2.334e-22]: * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-71.860 */ ra0u = LD80C(0xa1a091e0fb4f335a, -7, -9.86494298915814308249e-3L), ra1u = LD80C(0xc2b0d045ae37df6b, -1, -7.60510460864878271275e-1L), ra2u = LD80C(0xf2cec3ee7da636c5, 3, -1.51754798236892278250e+1L), ra3u = LD80C(0x813cc205395adc7d, 7, -1.29237335516455333420e+2L), ra4u = LD80C(0x8737c8b7b4062c2f, 9, -5.40871625829510494776e+2L), ra5u = LD80C(0x8ffe5383c08d4943, 10, -1.15194769466026108551e+3L), ra6u = LD80C(0x983573e64d5015a9, 10, -1.21767039790249025544e+3L), ra7u = LD80C(0x92a794e763a6d4db, 9, -5.86618463370624636688e+2L), ra8u = LD80C(0xd5ad1fae77c3d9a3, 6, -1.06838132335777049840e+2L), ra9u = LD80C(0x934c1a247807bb9c, 2, -4.60303980944467334806e+0L), sa1u = LD80C(0xd342f90012bb1189, 4, 2.64077014928547064865e+1L), sa2u = LD80C(0x839be13d9d5da883, 8, 2.63217811300123973067e+2L), sa3u = LD80C(0x9f8cba6d1ae1b24b, 10, 1.27639775710344617587e+3L), sa4u = LD80C(0xcaa83f403713e33e, 11, 3.24251544209971162003e+3L), sa5u = LD80C(0x8796aff2f3c47968, 12, 4.33883591261332837874e+3L), sa6u = LD80C(0xb6ef97f9c753157b, 11, 2.92697460344182158454e+3L), sa7u = LD80C(0xe02aee5f83773d1c, 9, 8.96670799139389559818e+2L), sa8u = LD80C(0xc82b83855b88e07e, 6, 1.00084987800048510018e+2L), sa9u = LD80C(0x92f030aefadf28ad, 1, 2.29591004455459083843e+0L); #define ra0 (ra0u.e) #define ra1 (ra1u.e) #define ra2 (ra2u.e) #define ra3 (ra3u.e) #define ra4 (ra4u.e) #define ra5 (ra5u.e) #define ra6 (ra6u.e) #define ra7 (ra7u.e) #define ra8 (ra8u.e) #define ra9 (ra9u.e) #define sa1 (sa1u.e) #define sa2 (sa2u.e) #define sa3 (sa3u.e) #define sa4 (sa4u.e) #define sa5 (sa5u.e) #define sa6 (sa6u.e) #define sa7 (sa7u.e) #define sa8 (sa8u.e) #define sa9 (sa9u.e) /* * Domain [2.85715,7], range ~[-8.323e-22,8.390e-22]: * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-70.326 */ static const union IEEEl2bits rb0u = LD80C(0xa1a091cf43abcd26, -7, -9.86494292470284646962e-3L), rb1u = LD80C(0xd19d2df1cbb8da0a, -1, -8.18804618389296662837e-1L), rb2u = LD80C(0x9a4dd1383e5daf5b, 4, -1.92879967111618594779e+1L), rb3u = LD80C(0xbff0ae9fc0751de6, 7, -1.91940164551245394969e+2L), rb4u = LD80C(0xdde08465310b472b, 9, -8.87508080766577324539e+2L), rb5u = LD80C(0xe796e1d38c8c70a9, 10, -1.85271506669474503781e+3L), rb6u = LD80C(0xbaf655a76e0ab3b5, 10, -1.49569795581333675349e+3L), rb7u = LD80C(0x95d21e3e75503c21, 8, -2.99641547972948019157e+2L), sb1u = LD80C(0x814487ed823c8cbd, 5, 3.23169247732868256569e+1L), sb2u = LD80C(0xbe4bfbb1301304be, 8, 3.80593618534539961773e+2L), sb3u = LD80C(0x809c4ade46b927c7, 11, 2.05776827838541292848e+3L), sb4u = LD80C(0xa55284359f3395a8, 12, 5.29031455540062116327e+3L), sb5u = LD80C(0xbcfa72da9b820874, 12, 6.04730608102312640462e+3L), sb6u = LD80C(0x9d09a35988934631, 11, 2.51260238030767176221e+3L), sb7u = LD80C(0xd675bbe542c159fa, 7, 2.14459898308561015684e+2L); #define rb0 (rb0u.e) #define rb1 (rb1u.e) #define rb2 (rb2u.e) #define rb3 (rb3u.e) #define rb4 (rb4u.e) #define rb5 (rb5u.e) #define rb6 (rb6u.e) #define rb7 (rb7u.e) #define sb1 (sb1u.e) #define sb2 (sb2u.e) #define sb3 (sb3u.e) #define sb4 (sb4u.e) #define sb5 (sb5u.e) #define sb6 (sb6u.e) #define sb7 (sb7u.e) /* * Domain [7,108], range ~[-4.422e-22,4.422e-22]: * |log(x*erfc(x)) + x**2 + 0.5625 - rc(x)/sc(x)| < 2**-70.938 */ static const union IEEEl2bits /* err = -4.422092275318925082e-22 -70.937689 */ rc0u = LD80C(0xa1a091cf437a17ad, -7, -9.86494292470008707260e-3L), rc1u = LD80C(0xbe79c5a978122b00, -1, -7.44045595049165939261e-1L), rc2u = LD80C(0xdb26f9bbe31a2794, 3, -1.36970155085888424425e+1L), rc3u = LD80C(0xb5f69a38f5747ac8, 6, -9.09816453742625888546e+1L), rc4u = LD80C(0xd79676d970d0a21a, 7, -2.15587750997584074147e+2L), rc5u = LD80C(0xfe528153c45ec97c, 6, -1.27161142938347796666e+2L), sc1u = LD80C(0xc5e8cd46d5604a96, 4, 2.47386727842204312937e+1L), sc2u = LD80C(0xc5f0f5a5484520eb, 7, 1.97941248254913378865e+2L), sc3u = LD80C(0x964e3c7b34db9170, 9, 6.01222441484087787522e+2L), sc4u = LD80C(0x99be1b89faa0596a, 9, 6.14970430845978077827e+2L), sc5u = LD80C(0xf80dfcbf37ffc5ea, 6, 1.24027318931184605891e+2L); #define rc0 (rc0u.e) #define rc1 (rc1u.e) #define rc2 (rc2u.e) #define rc3 (rc3u.e) #define rc4 (rc4u.e) #define rc5 (rc5u.e) #define sc1 (sc1u.e) #define sc2 (sc2u.e) #define sc3 (sc3u.e) #define sc4 (sc4u.e) #define sc5 (sc5u.e) long double erfl(long double x) { long double ax,R,S,P,Q,s,y,z,r; uint64_t lx; int32_t i; uint16_t hx; EXTRACT_LDBL80_WORDS(hx, lx, x); if((hx & 0x7fff) == 0x7fff) { /* erfl(nan)=nan */ i = (hx>>15)<<1; return (1-i)+one/x; /* erfl(+-inf)=+-1 */ } ENTERI(); ax = fabsl(x); if(ax < 0.84375) { if(ax < 0x1p-34L) { if(ax < 0x1p-16373L) RETURNI((8*x+efx8*x)/8); /* avoid spurious underflow */ RETURNI(x + efx*x); } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5)))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6))))); y = r/s; RETURNI(x + x*y); } if(ax < 1.25) { s = ax-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7)))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7)))))); if(x>=0) RETURNI(erx + P/Q); else RETURNI(-erx - P/Q); } if(ax >= 7) { /* inf>|x|>= 7 */ if(x>=0) RETURNI(one-tiny); else RETURNI(tiny-one); } s = one/(ax*ax); if(ax < 2.85715) { /* |x| < 2.85715 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+ s*(ra8+s*ra9)))))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*(sa8+s*sa9)))))))); } else { /* |x| >= 2.85715 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7)))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))); } z=(float)ax; r=expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S); if(x>=0) RETURNI(one-r/ax); else RETURNI(r/ax-one); } long double erfcl(long double x) { long double ax,R,S,P,Q,s,y,z,r; uint64_t lx; uint16_t hx; EXTRACT_LDBL80_WORDS(hx, lx, x); if((hx & 0x7fff) == 0x7fff) { /* erfcl(nan)=nan */ /* erfcl(+-inf)=0,2 */ return ((hx>>15)<<1)+one/x; } ENTERI(); ax = fabsl(x); if(ax < 0.84375L) { if(ax < 0x1p-34L) RETURNI(one-x); z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5)))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6))))); y = r/s; if(ax < 0.25L) { /* x<1/4 */ RETURNI(one-(x+x*y)); } else { r = x*y; r += (x-half); RETURNI(half - r); } } if(ax < 1.25L) { s = ax-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7)))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7)))))); if(x>=0) { z = one-erx; RETURNI(z - P/Q); } else { z = (erx+P/Q); RETURNI(one+z); } } if(ax < 108) { /* |x| < 108 */ s = one/(ax*ax); if(ax < 2.85715) { /* |x| < 2.85715 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+ s*(ra8+s*ra9)))))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*(sa8+s*sa9)))))))); } else if(ax < 7) { /* | |x| < 7 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7)))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))); } else { if(x < -7) RETURNI(two-tiny);/* x < -7 */ R=rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*rc5)))); S=one+s*(sc1+s*(sc2+s*(sc3+s*(sc4+s*sc5)))); } z = (float)ax; r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S); if(x>0) RETURNI(r/ax); else RETURNI(two-r/ax); } else { if(x>0) RETURNI(tiny*tiny); else RETURNI(two-tiny); } } diff --git a/lib/msun/ld80/s_exp2l.c b/lib/msun/ld80/s_exp2l.c index 94aecf1843cd..9d979994ece8 100644 --- a/lib/msun/ld80/s_exp2l.c +++ b/lib/msun/ld80/s_exp2l.c @@ -1,288 +1,287 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #define TBLBITS 7 #define TBLSIZE (1 << TBLBITS) #define BIAS (LDBL_MAX_EXP - 1) static volatile long double huge = 0x1p10000L, twom10000 = 0x1p-10000L; static const union IEEEl2bits P1 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309429e-1L); static const double redux = 0x1.8p63 / TBLSIZE, /* * Domain [-0.00390625, 0.00390625], range ~[-1.7079e-23, 1.7079e-23] * |exp(x) - p(x)| < 2**-75.6 */ P2 = 2.4022650695910072e-1, /* 0x1ebfbdff82c58f.0p-55 */ P3 = 5.5504108664816879e-2, /* 0x1c6b08d7049e1a.0p-57 */ P4 = 9.6181291055695180e-3, /* 0x13b2ab6fa8321a.0p-59 */ P5 = 1.3333563089183052e-3, /* 0x15d8806f67f251.0p-62 */ P6 = 1.5413361552277414e-4; /* 0x1433ddacff3441.0p-65 */ static const double tbl[TBLSIZE * 2] = { 0x1.6a09e667f3bcdp-1, -0x1.bdd3413b2648p-55, 0x1.6c012750bdabfp-1, -0x1.2895667ff0cp-57, 0x1.6dfb23c651a2fp-1, -0x1.bbe3a683c88p-58, 0x1.6ff7df9519484p-1, -0x1.83c0f25860fp-56, 0x1.71f75e8ec5f74p-1, -0x1.16e4786887bp-56, 0x1.73f9a48a58174p-1, -0x1.0a8d96c65d5p-55, 0x1.75feb564267c9p-1, -0x1.0245957316ep-55, 0x1.780694fde5d3fp-1, 0x1.866b80a0216p-55, 0x1.7a11473eb0187p-1, -0x1.41577ee0499p-56, 0x1.7c1ed0130c132p-1, 0x1.f124cd1164ep-55, 0x1.7e2f336cf4e62p-1, 0x1.05d02ba157ap-57, 0x1.80427543e1a12p-1, -0x1.27c86626d97p-55, 0x1.82589994cce13p-1, -0x1.d4c1dd41533p-55, 0x1.8471a4623c7adp-1, -0x1.8d684a341cep-56, 0x1.868d99b4492edp-1, -0x1.fc6f89bd4f68p-55, 0x1.88ac7d98a6699p-1, 0x1.994c2f37cb5p-55, 0x1.8ace5422aa0dbp-1, 0x1.6e9f156864bp-55, 0x1.8cf3216b5448cp-1, -0x1.0d55e32e9e4p-57, 0x1.8f1ae99157736p-1, 0x1.5cc13a2e397p-56, 0x1.9145b0b91ffc6p-1, -0x1.dd6792e5825p-55, 0x1.93737b0cdc5e5p-1, -0x1.75fc781b58p-58, 0x1.95a44cbc8520fp-1, -0x1.64b7c96a5fp-57, 0x1.97d829fde4e5p-1, -0x1.d185b7c1b86p-55, 0x1.9a0f170ca07bap-1, -0x1.173bd91cee6p-55, 0x1.9c49182a3f09p-1, 0x1.c7c46b071f2p-57, 0x1.9e86319e32323p-1, 0x1.824ca78e64cp-57, 0x1.a0c667b5de565p-1, -0x1.359495d1cd5p-55, 0x1.a309bec4a2d33p-1, 0x1.6305c7ddc368p-55, 0x1.a5503b23e255dp-1, -0x1.d2f6edb8d42p-55, 0x1.a799e1330b358p-1, 0x1.bcb7ecac564p-55, 0x1.a9e6b5579fdbfp-1, 0x1.0fac90ef7fdp-55, 0x1.ac36bbfd3f37ap-1, -0x1.f9234cae76dp-56, 0x1.ae89f995ad3adp-1, 0x1.7a1cd345dcc8p-55, 0x1.b0e07298db666p-1, -0x1.bdef54c80e4p-55, 0x1.b33a2b84f15fbp-1, -0x1.2805e3084d8p-58, 0x1.b59728de5593ap-1, -0x1.c71dfbbba6ep-55, 0x1.b7f76f2fb5e47p-1, -0x1.5584f7e54acp-57, 0x1.ba5b030a1064ap-1, -0x1.efcd30e5429p-55, 0x1.bcc1e904bc1d2p-1, 0x1.23dd07a2d9fp-56, 0x1.bf2c25bd71e09p-1, -0x1.efdca3f6b9c8p-55, 0x1.c199bdd85529cp-1, 0x1.11065895049p-56, 0x1.c40ab5fffd07ap-1, 0x1.b4537e083c6p-55, 0x1.c67f12e57d14bp-1, 0x1.2884dff483c8p-55, 0x1.c8f6d9406e7b5p-1, 0x1.1acbc48805cp-57, 0x1.cb720dcef9069p-1, 0x1.503cbd1e94ap-57, 0x1.cdf0b555dc3fap-1, -0x1.dd83b53829dp-56, 0x1.d072d4a07897cp-1, -0x1.cbc3743797a8p-55, 0x1.d2f87080d89f2p-1, -0x1.d487b719d858p-55, 0x1.d5818dcfba487p-1, 0x1.2ed02d75b37p-56, 0x1.d80e316c98398p-1, -0x1.11ec18bedep-55, 0x1.da9e603db3285p-1, 0x1.c2300696db5p-55, 0x1.dd321f301b46p-1, 0x1.2da5778f019p-55, 0x1.dfc97337b9b5fp-1, -0x1.1a5cd4f184b8p-55, 0x1.e264614f5a129p-1, -0x1.7b627817a148p-55, 0x1.e502ee78b3ff6p-1, 0x1.39e8980a9cdp-56, 0x1.e7a51fbc74c83p-1, 0x1.2d522ca0c8ep-55, 0x1.ea4afa2a490dap-1, -0x1.e9c23179c288p-55, 0x1.ecf482d8e67f1p-1, -0x1.c93f3b411ad8p-55, 0x1.efa1bee615a27p-1, 0x1.dc7f486a4b68p-55, 0x1.f252b376bba97p-1, 0x1.3a1a5bf0d8e8p-55, 0x1.f50765b6e454p-1, 0x1.9d3e12dd8a18p-55, 0x1.f7bfdad9cbe14p-1, -0x1.dbb12d00635p-55, 0x1.fa7c1819e90d8p-1, 0x1.74853f3a593p-56, 0x1.fd3c22b8f71f1p-1, 0x1.2eb74966578p-58, 0x1p+0, 0x0p+0, 0x1.0163da9fb3335p+0, 0x1.b61299ab8cd8p-54, 0x1.02c9a3e778061p+0, -0x1.19083535b08p-56, 0x1.04315e86e7f85p+0, -0x1.0a31c1977c98p-54, 0x1.059b0d3158574p+0, 0x1.d73e2a475b4p-55, 0x1.0706b29ddf6dep+0, -0x1.c91dfe2b13cp-55, 0x1.0874518759bc8p+0, 0x1.186be4bb284p-57, 0x1.09e3ecac6f383p+0, 0x1.14878183161p-54, 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc61p-54, 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f8p-54, 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c58p-59, 0x1.0fb66affed31bp+0, -0x1.b9bedc44ebcp-57, 0x1.11301d0125b51p+0, -0x1.6c51039449bp-54, 0x1.12abdc06c31ccp+0, -0x1.1b514b36ca8p-58, 0x1.1429aaea92dep+0, -0x1.32fbf9af1368p-54, 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeabp-55, 0x1.172b83c7d517bp+0, -0x1.19041b9d78ap-55, 0x1.18af9388c8deap+0, -0x1.11023d1970f8p-54, 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4969p-55, 0x1.1bbe084045cd4p+0, -0x1.95386352ef6p-54, 0x1.1d4873168b9aap+0, 0x1.e016e00a264p-54, 0x1.1ed5022fcd91dp+0, -0x1.1df98027bb78p-54, 0x1.2063b88628cd6p+0, 0x1.dc775814a85p-55, 0x1.21f49917ddc96p+0, 0x1.2a97e9494a6p-55, 0x1.2387a6e756238p+0, 0x1.9b07eb6c7058p-54, 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f5p-55, 0x1.26b4565e27cddp+0, 0x1.2bd339940eap-55, 0x1.284dfe1f56381p+0, -0x1.a4c3a8c3f0d8p-54, 0x1.29e9df51fdee1p+0, 0x1.612e8afad12p-55, 0x1.2b87fd0dad99p+0, -0x1.10adcd6382p-59, 0x1.2d285a6e4030bp+0, 0x1.0024754db42p-54, 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d524p-56, 0x1.306fe0a31b715p+0, 0x1.6f46ad23183p-55, 0x1.32170fc4cd831p+0, 0x1.a9ce78e1804p-55, 0x1.33c08b26416ffp+0, 0x1.327218436598p-54, 0x1.356c55f929ff1p+0, -0x1.b5cee5c4e46p-55, 0x1.371a7373aa9cbp+0, -0x1.63aeabf42ebp-54, 0x1.38cae6d05d866p+0, -0x1.e958d3c99048p-54, 0x1.3a7db34e59ff7p+0, -0x1.5e436d661f6p-56, 0x1.3c32dc313a8e5p+0, -0x1.efff8375d2ap-54, 0x1.3dea64c123422p+0, 0x1.ada0911f09fp-55, 0x1.3fa4504ac801cp+0, -0x1.7d023f956fap-54, 0x1.4160a21f72e2ap+0, -0x1.ef3691c309p-58, 0x1.431f5d950a897p+0, -0x1.1c7dde35f7ap-55, 0x1.44e086061892dp+0, 0x1.89b7a04ef8p-59, 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a8p-54, 0x1.486a2b5c13cdp+0, 0x1.3c1a3b69062p-56, 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be8p-54, 0x1.4bfdad5362a27p+0, 0x1.d4397afec42p-56, 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a78p-54, 0x1.4f9b2769d2ca7p+0, -0x1.4b309d25958p-54, 0x1.516daa2cf6642p+0, -0x1.f768569bd94p-55, 0x1.5342b569d4f82p+0, -0x1.07abe1db13dp-55, 0x1.551a4ca5d920fp+0, -0x1.d689cefede6p-55, 0x1.56f4736b527dap+0, 0x1.9bb2c011d938p-54, 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1ep-55, 0x1.5ab07dd485429p+0, 0x1.6324c0546478p-54, 0x1.5c9268a5946b7p+0, 0x1.c4b1b81698p-60, 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e68p-54, 0x1.605e1b976dc09p+0, -0x1.3e2429b56de8p-54, 0x1.6247eb03a5585p+0, -0x1.383c17e40b48p-54, 0x1.6434634ccc32p+0, -0x1.c483c759d89p-55, 0x1.6623882552225p+0, -0x1.bb60987591cp-54, 0x1.68155d44ca973p+0, 0x1.038ae44f74p-57, }; /** * Compute the base 2 exponential of x for Intel 80-bit format. * * Accuracy: Peak error < 0.511 ulp. * * Method: (equally-spaced tables) * * Reduce x: * x = 2**k + y, for integer k and |y| <= 1/2. * Thus we have exp2l(x) = 2**k * exp2(y). * * Reduce y: * y = i/TBLSIZE + z for integer i near y * TBLSIZE. * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z), * with |z| <= 2**-(TBLBITS+1). * * We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a * degree-6 minimax polynomial with maximum error under 2**-75.6. * The table entries each have 104 bits of accuracy, encoded as * a pair of double precision values. */ long double exp2l(long double x) { union IEEEl2bits u, v; long double r, twopk, twopkp10000, z; uint32_t hx, ix, i0; int k; /* Filter out exceptional cases. */ u.e = x; hx = u.xbits.expsign; ix = hx & 0x7fff; if (ix >= BIAS + 14) { /* |x| >= 16384 or x is NaN */ if (ix == BIAS + LDBL_MAX_EXP) { if (hx & 0x8000 && u.xbits.man == 1ULL << 63) return (0.0L); /* x is -Inf */ return (x + x); /* x is +Inf, NaN or unsupported */ } if (x >= 16384) return (huge * huge); /* overflow */ if (x <= -16446) return (twom10000 * twom10000); /* underflow */ } else if (ix <= BIAS - 66) { /* |x| < 0x1p-65 (includes pseudos) */ return (1.0L + x); /* 1 with inexact */ } ENTERI(); /* * Reduce x, computing z, i0, and k. The low bits of x + redux * contain the 16-bit integer part of the exponent (k) followed by * TBLBITS fractional bits (i0). We use bit tricks to extract these * as integers, then set z to the remainder. * * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8. * Then the low-order word of x + redux is 0x000abc12, * We split this into k = 0xabc and i0 = 0x12 (adjusted to * index into the table), then we compute z = 0x0.003456p0. * * XXX If the exponent is negative, the computation of k depends on * '>>' doing sign extension. */ u.e = x + redux; i0 = u.bits.manl + TBLSIZE / 2; k = (int)i0 >> TBLBITS; i0 = (i0 & (TBLSIZE - 1)) << 1; u.e -= redux; z = x - u.e; v.xbits.man = 1ULL << 63; if (k >= LDBL_MIN_EXP) { v.xbits.expsign = BIAS + k; twopk = v.e; } else { v.xbits.expsign = BIAS + k + 10000; twopkp10000 = v.e; } /* Compute r = exp2l(y) = exp2lt[i0] * p(z). */ long double t_hi = tbl[i0]; long double t_lo = tbl[i0 + 1]; r = t_lo + (t_hi + t_lo) * z * (P1.e + z * (P2 + z * (P3 + z * (P4 + z * (P5 + z * P6))))) + t_hi; /* Scale by 2**k. */ if (k >= LDBL_MIN_EXP) { if (k == LDBL_MAX_EXP) RETURNI(r * 2.0 * 0x1p16383L); RETURNI(r * twopk); } else { RETURNI(r * twopkp10000 * twom10000); } } diff --git a/lib/msun/ld80/s_expl.c b/lib/msun/ld80/s_expl.c index 065e02fae1b0..03d7b366151a 100644 --- a/lib/msun/ld80/s_expl.c +++ b/lib/msun/ld80/s_expl.c @@ -1,273 +1,272 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009-2013 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Optimized by Bruce D. Evans. */ -#include /** * Compute the exponential of x for Intel 80-bit format. This is based on: * * PTP Tang, "Table-driven implementation of the exponential function * in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 15, * 144-157 (1989). * * where the 32 table entries have been expanded to INTERVALS (see below). */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #include "k_expl.h" /* XXX Prevent compilers from erroneously constant folding these: */ static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L; static const long double twom10000 = 0x1p-10000L; static const union IEEEl2bits /* log(2**16384 - 0.5) rounded towards zero: */ /* log(2**16384 - 0.5 + 1) rounded towards zero for expm1l() is the same: */ o_thresholdu = LD80C(0xb17217f7d1cf79ab, 13, 11356.5234062941439488L), #define o_threshold (o_thresholdu.e) /* log(2**(-16381-64-1)) rounded towards zero: */ u_thresholdu = LD80C(0xb21dfe7f09e2baa9, 13, -11399.4985314888605581L); #define u_threshold (u_thresholdu.e) long double expl(long double x) { union IEEEl2bits u; long double hi, lo, t, twopk; int k; uint16_t hx, ix; /* Filter out exceptional cases. */ u.e = x; hx = u.xbits.expsign; ix = hx & 0x7fff; if (ix >= BIAS + 13) { /* |x| >= 8192 or x is NaN */ if (ix == BIAS + LDBL_MAX_EXP) { if (hx & 0x8000) /* x is -Inf, -NaN or unsupported */ RETURNF(-1 / x); RETURNF(x + x); /* x is +Inf, +NaN or unsupported */ } if (x > o_threshold) RETURNF(huge * huge); if (x < u_threshold) RETURNF(tiny * tiny); } else if (ix < BIAS - 75) { /* |x| < 0x1p-75 (includes pseudos) */ RETURNF(1 + x); /* 1 with inexact iff x != 0 */ } ENTERI(); twopk = 1; __k_expl(x, &hi, &lo, &k); t = SUM2P(hi, lo); /* Scale by 2**k. */ if (k >= LDBL_MIN_EXP) { if (k == LDBL_MAX_EXP) RETURNI(t * 2 * 0x1p16383L); SET_LDBL_EXPSIGN(twopk, BIAS + k); RETURNI(t * twopk); } else { SET_LDBL_EXPSIGN(twopk, BIAS + k + 10000); RETURNI(t * twopk * twom10000); } } /** * Compute expm1l(x) for Intel 80-bit format. This is based on: * * PTP Tang, "Table-driven implementation of the Expm1 function * in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 18, * 211-222 (1992). */ /* * Our T1 and T2 are chosen to be approximately the points where method * A and method B have the same accuracy. Tang's T1 and T2 are the * points where method A's accuracy changes by a full bit. For Tang, * this drop in accuracy makes method A immediately less accurate than * method B, but our larger INTERVALS makes method A 2 bits more * accurate so it remains the most accurate method significantly * closer to the origin despite losing the full bit in our extended * range for it. */ static const double T1 = -0.1659, /* ~-30.625/128 * log(2) */ T2 = 0.1659; /* ~30.625/128 * log(2) */ /* * Domain [-0.1659, 0.1659], range ~[-2.6155e-22, 2.5507e-23]: * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-71.6 * * XXX the coeffs aren't very carefully rounded, and I get 2.8 more bits, * but unlike for ld128 we can't drop any terms. */ static const union IEEEl2bits B3 = LD80C(0xaaaaaaaaaaaaaaab, -3, 1.66666666666666666671e-1L), B4 = LD80C(0xaaaaaaaaaaaaaaac, -5, 4.16666666666666666712e-2L); static const double B5 = 8.3333333333333245e-3, /* 0x1.111111111110cp-7 */ B6 = 1.3888888888888861e-3, /* 0x1.6c16c16c16c0ap-10 */ B7 = 1.9841269841532042e-4, /* 0x1.a01a01a0319f9p-13 */ B8 = 2.4801587302069236e-5, /* 0x1.a01a01a03cbbcp-16 */ B9 = 2.7557316558468562e-6, /* 0x1.71de37fd33d67p-19 */ B10 = 2.7557315829785151e-7, /* 0x1.27e4f91418144p-22 */ B11 = 2.5063168199779829e-8, /* 0x1.ae94fabdc6b27p-26 */ B12 = 2.0887164654459567e-9; /* 0x1.1f122d6413fe1p-29 */ long double expm1l(long double x) { union IEEEl2bits u, v; long double fn, hx2_hi, hx2_lo, q, r, r1, r2, t, twomk, twopk, x_hi; long double x_lo, x2, z; long double x4; int k, n, n2; uint16_t hx, ix; /* Filter out exceptional cases. */ u.e = x; hx = u.xbits.expsign; ix = hx & 0x7fff; if (ix >= BIAS + 6) { /* |x| >= 64 or x is NaN */ if (ix == BIAS + LDBL_MAX_EXP) { if (hx & 0x8000) /* x is -Inf, -NaN or unsupported */ RETURNF(-1 / x - 1); RETURNF(x + x); /* x is +Inf, +NaN or unsupported */ } if (x > o_threshold) RETURNF(huge * huge); /* * expm1l() never underflows, but it must avoid * unrepresentable large negative exponents. We used a * much smaller threshold for large |x| above than in * expl() so as to handle not so large negative exponents * in the same way as large ones here. */ if (hx & 0x8000) /* x <= -64 */ RETURNF(tiny - 1); /* good for x < -65ln2 - eps */ } ENTERI(); if (T1 < x && x < T2) { if (ix < BIAS - 74) { /* |x| < 0x1p-74 (includes pseudos) */ /* x (rounded) with inexact if x != 0: */ RETURNI(x == 0 ? x : (0x1p100 * x + fabsl(x)) * 0x1p-100); } x2 = x * x; x4 = x2 * x2; q = x4 * (x2 * (x4 * /* * XXX the number of terms is no longer good for * pairwise grouping of all except B3, and the * grouping is no longer from highest down. */ (x2 * B12 + (x * B11 + B10)) + (x2 * (x * B9 + B8) + (x * B7 + B6))) + (x * B5 + B4.e)) + x2 * x * B3.e; x_hi = (float)x; x_lo = x - x_hi; hx2_hi = x_hi * x_hi / 2; hx2_lo = x_lo * (x + x_hi) / 2; if (ix >= BIAS - 7) RETURNI((hx2_hi + x_hi) + (hx2_lo + x_lo + q)); else RETURNI(x + (hx2_lo + q + hx2_hi)); } /* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */ fn = rnintl(x * INV_L); n = irint(fn); n2 = (unsigned)n % INTERVALS; k = n >> LOG2_INTERVALS; r1 = x - fn * L1; r2 = fn * -L2; r = r1 + r2; /* Prepare scale factor. */ v.e = 1; v.xbits.expsign = BIAS + k; twopk = v.e; /* * Evaluate lower terms of * expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */ z = r * r; q = r2 + z * (A2 + r * A3) + z * z * (A4 + r * A5) + z * z * z * A6; t = (long double)tbl[n2].lo + tbl[n2].hi; if (k == 0) { t = SUM2P(tbl[n2].hi - 1, tbl[n2].lo * (r1 + 1) + t * q + tbl[n2].hi * r1); RETURNI(t); } if (k == -1) { t = SUM2P(tbl[n2].hi - 2, tbl[n2].lo * (r1 + 1) + t * q + tbl[n2].hi * r1); RETURNI(t / 2); } if (k < -7) { t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1)); RETURNI(t * twopk - 1); } if (k > 2 * LDBL_MANT_DIG - 1) { t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1)); if (k == LDBL_MAX_EXP) RETURNI(t * 2 * 0x1p16383L - 1); RETURNI(t * twopk - 1); } v.xbits.expsign = BIAS - k; twomk = v.e; if (k > LDBL_MANT_DIG - 1) t = SUM2P(tbl[n2].hi, tbl[n2].lo - twomk + t * (q + r1)); else t = SUM2P(tbl[n2].hi - twomk, tbl[n2].lo + t * (q + r1)); RETURNI(t * twopk); } diff --git a/lib/msun/ld80/s_logl.c b/lib/msun/ld80/s_logl.c index 459374d7d164..2c5d1e2dd08f 100644 --- a/lib/msun/ld80/s_logl.c +++ b/lib/msun/ld80/s_logl.c @@ -1,716 +1,715 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007-2013 Bruce D. Evans * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include /** * Implementation of the natural logarithm of x for Intel 80-bit format. * * First decompose x into its base 2 representation: * * log(x) = log(X * 2**k), where X is in [1, 2) * = log(X) + k * log(2). * * Let X = X_i + e, where X_i is the center of one of the intervals * [-1.0/256, 1.0/256), [1.0/256, 3.0/256), .... [2.0-1.0/256, 2.0+1.0/256) * and X is in this interval. Then * * log(X) = log(X_i + e) * = log(X_i * (1 + e / X_i)) * = log(X_i) + log(1 + e / X_i). * * The values log(X_i) are tabulated below. Let d = e / X_i and use * * log(1 + d) = p(d) * * where p(d) = d - 0.5*d*d + ... is a special minimax polynomial of * suitably high degree. * * To get sufficiently small roundoff errors, k * log(2), log(X_i), and * sometimes (if |k| is not large) the first term in p(d) must be evaluated * and added up in extra precision. Extra precision is not needed for the * rest of p(d). In the worst case when k = 0 and log(X_i) is 0, the final * error is controlled mainly by the error in the second term in p(d). The * error in this term itself is at most 0.5 ulps from the d*d operation in * it. The error in this term relative to the first term is thus at most * 0.5 * |-0.5| * |d| < 1.0/1024 ulps. We aim for an accumulated error of * at most twice this at the point of the final rounding step. Thus the * final error should be at most 0.5 + 1.0/512 = 0.5020 ulps. Exhaustive * testing of a float variant of this function showed a maximum final error * of 0.5008 ulps. Non-exhaustive testing of a double variant of this * function showed a maximum final error of 0.5078 ulps (near 1+1.0/256). * * We made the maximum of |d| (and thus the total relative error and the * degree of p(d)) small by using a large number of intervals. Using * centers of intervals instead of endpoints reduces this maximum by a * factor of 2 for a given number of intervals. p(d) is special only * in beginning with the Taylor coefficients 0 + 1*d, which tends to happen * naturally. The most accurate minimax polynomial of a given degree might * be different, but then we wouldn't want it since we would have to do * extra work to avoid roundoff error (especially for P0*d instead of d). */ #ifdef DEBUG #include #include #endif #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #define i386_SSE_GOOD #ifndef NO_STRUCT_RETURN #define STRUCT_RETURN #endif #include "math_private.h" #if !defined(NO_UTAB) && !defined(NO_UTABL) #define USE_UTAB #endif /* * Domain [-0.005280, 0.004838], range ~[-5.1736e-22, 5.1738e-22]: * |log(1 + d)/d - p(d)| < 2**-70.7 */ static const double P2 = -0.5, P3 = 3.3333333333333359e-1, /* 0x1555555555555a.0p-54 */ P4 = -2.5000000000004424e-1, /* -0x1000000000031d.0p-54 */ P5 = 1.9999999992970016e-1, /* 0x1999999972f3c7.0p-55 */ P6 = -1.6666666072191585e-1, /* -0x15555548912c09.0p-55 */ P7 = 1.4286227413310518e-1, /* 0x12494f9d9def91.0p-55 */ P8 = -1.2518388626763144e-1; /* -0x1006068cc0b97c.0p-55 */ static volatile const double zero = 0; #define INTERVALS 128 #define LOG2_INTERVALS 7 #define TSIZE (INTERVALS + 1) #define G(i) (T[(i)].G) #define F_hi(i) (T[(i)].F_hi) #define F_lo(i) (T[(i)].F_lo) #define ln2_hi F_hi(TSIZE - 1) #define ln2_lo F_lo(TSIZE - 1) #define E(i) (U[(i)].E) #define H(i) (U[(i)].H) static const struct { float G; /* 1/(1 + i/128) rounded to 8/9 bits */ float F_hi; /* log(1 / G_i) rounded (see below) */ double F_lo; /* next 53 bits for log(1 / G_i) */ } T[TSIZE] = { /* * ln2_hi and each F_hi(i) are rounded to a number of bits that * makes F_hi(i) + dk*ln2_hi exact for all i and all dk. * * The last entry (for X just below 2) is used to define ln2_hi * and ln2_lo, to ensure that F_hi(i) and F_lo(i) cancel exactly * with dk*ln2_hi and dk*ln2_lo, respectively, when dk = -1. * This is needed for accuracy when x is just below 1. (To avoid * special cases, such x are "reduced" strangely to X just below * 2 and dk = -1, and then the exact cancellation is needed * because any the error from any non-exactness would be too * large). * * We want to share this table between double precision and ld80, * so the relevant range of dk is the larger one of ld80 * ([-16445, 16383]) and the relevant exactness requirement is * the stricter one of double precision. The maximum number of * bits in F_hi(i) that works is very dependent on i but has * a minimum of 33. We only need about 12 bits in F_hi(i) for * it to provide enough extra precision in double precision (11 * more than that are required for ld80). * * We round F_hi(i) to 24 bits so that it can have type float, * mainly to minimize the size of the table. Using all 24 bits * in a float for it automatically satisfies the above constraints. */ { 0x800000.0p-23, 0, 0 }, { 0xfe0000.0p-24, 0x8080ac.0p-30, -0x14ee431dae6675.0p-84 }, { 0xfc0000.0p-24, 0x8102b3.0p-29, -0x1db29ee2d83718.0p-84 }, { 0xfa0000.0p-24, 0xc24929.0p-29, 0x1191957d173698.0p-83 }, { 0xf80000.0p-24, 0x820aec.0p-28, 0x13ce8888e02e79.0p-82 }, { 0xf60000.0p-24, 0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82 }, { 0xf48000.0p-24, 0xbc42cb.0p-28, -0x172a21161a1076.0p-83 }, { 0xf30000.0p-24, 0xd57797.0p-28, -0x1e09de07cb9589.0p-82 }, { 0xf10000.0p-24, 0xf7518e.0p-28, 0x1ae1eec1b036c5.0p-91 }, { 0xef0000.0p-24, 0x8cb9df.0p-27, -0x1d7355325d560e.0p-81 }, { 0xed8000.0p-24, 0x999ec0.0p-27, -0x1f9f02d256d503.0p-82 }, { 0xec0000.0p-24, 0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83 }, { 0xea0000.0p-24, 0xb80698.0p-27, 0x15d581c1e8da9a.0p-81 }, { 0xe80000.0p-24, 0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83 }, { 0xe70000.0p-24, 0xd273b2.0p-27, 0x163786f5251af0.0p-85 }, { 0xe50000.0p-24, 0xe442c0.0p-27, 0x1bc4b2368e32d5.0p-84 }, { 0xe38000.0p-24, 0xf1b83f.0p-27, 0x1c6090f684e676.0p-81 }, { 0xe20000.0p-24, 0xff448a.0p-27, -0x1890aa69ac9f42.0p-82 }, { 0xe08000.0p-24, 0x8673f6.0p-26, 0x1b9985194b6b00.0p-80 }, { 0xdf0000.0p-24, 0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83 }, { 0xdd8000.0p-24, 0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82 }, { 0xdc0000.0p-24, 0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80 }, { 0xda8000.0p-24, 0xa2315d.0p-26, -0x11b26121629c47.0p-82 }, { 0xd90000.0p-24, 0xa93f2f.0p-26, 0x1286d633e8e569.0p-81 }, { 0xd78000.0p-24, 0xb05988.0p-26, 0x16128eba936770.0p-84 }, { 0xd60000.0p-24, 0xb78094.0p-26, 0x16ead577390d32.0p-80 }, { 0xd50000.0p-24, 0xbc4c6c.0p-26, 0x151131ccf7c7b7.0p-81 }, { 0xd38000.0p-24, 0xc3890a.0p-26, -0x115e2cd714bd06.0p-80 }, { 0xd20000.0p-24, 0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82 }, { 0xd10000.0p-24, 0xcfb620.0p-26, 0x1c2259904d6866.0p-81 }, { 0xcf8000.0p-24, 0xd71653.0p-26, 0x1ece57a8d5ae55.0p-80 }, { 0xce0000.0p-24, 0xde843a.0p-26, -0x1f109d4bc45954.0p-81 }, { 0xcd0000.0p-24, 0xe37fde.0p-26, 0x1bc03dc271a74d.0p-81 }, { 0xcb8000.0p-24, 0xeb050c.0p-26, -0x1bf2badc0df842.0p-85 }, { 0xca0000.0p-24, 0xf29878.0p-26, -0x18efededd89fbe.0p-87 }, { 0xc90000.0p-24, 0xf7ad6f.0p-26, 0x1373ff977baa69.0p-81 }, { 0xc80000.0p-24, 0xfcc8e3.0p-26, 0x196766f2fb3283.0p-80 }, { 0xc68000.0p-24, 0x823f30.0p-25, 0x19bd076f7c434e.0p-79 }, { 0xc58000.0p-24, 0x84d52c.0p-25, -0x1a327257af0f46.0p-79 }, { 0xc40000.0p-24, 0x88bc74.0p-25, 0x113f23def19c5a.0p-81 }, { 0xc30000.0p-24, 0x8b5ae6.0p-25, 0x1759f6e6b37de9.0p-79 }, { 0xc20000.0p-24, 0x8dfccb.0p-25, 0x1ad35ca6ed5148.0p-81 }, { 0xc10000.0p-24, 0x90a22b.0p-25, 0x1a1d71a87deba4.0p-79 }, { 0xbf8000.0p-24, 0x94a0d8.0p-25, -0x139e5210c2b731.0p-80 }, { 0xbe8000.0p-24, 0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81 }, { 0xbd8000.0p-24, 0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79 }, { 0xbc8000.0p-24, 0x9cb672.0p-25, -0x14c8815839c566.0p-79 }, { 0xbb0000.0p-24, 0xa0cda1.0p-25, 0x1eaf46390dbb24.0p-81 }, { 0xba0000.0p-24, 0xa38c6e.0p-25, 0x138e20d831f698.0p-81 }, { 0xb90000.0p-24, 0xa64f05.0p-25, -0x1e8d3c41123616.0p-82 }, { 0xb80000.0p-24, 0xa91570.0p-25, 0x1ce28f5f3840b2.0p-80 }, { 0xb70000.0p-24, 0xabdfbb.0p-25, -0x186e5c0a424234.0p-79 }, { 0xb60000.0p-24, 0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83 }, { 0xb50000.0p-24, 0xb18018.0p-25, 0x16755892770634.0p-79 }, { 0xb40000.0p-24, 0xb45642.0p-25, -0x16395ebe59b152.0p-82 }, { 0xb30000.0p-24, 0xb73077.0p-25, 0x1abc65c8595f09.0p-80 }, { 0xb20000.0p-24, 0xba0ec4.0p-25, -0x1273089d3dad89.0p-79 }, { 0xb10000.0p-24, 0xbcf133.0p-25, 0x10f9f67b1f4bbf.0p-79 }, { 0xb00000.0p-24, 0xbfd7d2.0p-25, -0x109fab90486409.0p-80 }, { 0xaf0000.0p-24, 0xc2c2ac.0p-25, -0x1124680aa43333.0p-79 }, { 0xae8000.0p-24, 0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80 }, { 0xad8000.0p-24, 0xc72afd.0p-25, -0x132d91f21d89c9.0p-80 }, { 0xac8000.0p-24, 0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79 }, { 0xab8000.0p-24, 0xcd1aae.0p-25, 0x19deb5ce6a6a87.0p-81 }, { 0xaa8000.0p-24, 0xd0192f.0p-25, 0x1a29fb48f7d3cb.0p-79 }, { 0xaa0000.0p-24, 0xd19a20.0p-25, 0x1127d3c6457f9d.0p-81 }, { 0xa90000.0p-24, 0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81 }, { 0xa80000.0p-24, 0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79 }, { 0xa70000.0p-24, 0xdab7d0.0p-25, 0x1118a425494b61.0p-80 }, { 0xa68000.0p-24, 0xdc40d5.0p-25, 0x1966f24d29d3a3.0p-80 }, { 0xa58000.0p-24, 0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82 }, { 0xa48000.0p-24, 0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80 }, { 0xa40000.0p-24, 0xe3ffce.0p-25, 0x1d155324911f57.0p-80 }, { 0xa30000.0p-24, 0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80 }, { 0xa20000.0p-24, 0xea4812.0p-25, 0x1b7be9add7f4d4.0p-80 }, { 0xa18000.0p-24, 0xebdd3d.0p-25, 0x1b3cfb3f7511dd.0p-79 }, { 0xa08000.0p-24, 0xef0b5b.0p-25, -0x1220de1f730190.0p-79 }, { 0xa00000.0p-24, 0xf0a451.0p-25, -0x176364c9ac81cd.0p-80 }, { 0x9f0000.0p-24, 0xf3da16.0p-25, 0x1eed6b9aafac8d.0p-81 }, { 0x9e8000.0p-24, 0xf576e9.0p-25, 0x1d593218675af2.0p-79 }, { 0x9d8000.0p-24, 0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84 }, { 0x9d0000.0p-24, 0xfa553f.0p-25, 0x1c063259bcade0.0p-79 }, { 0x9c0000.0p-24, 0xfd9ac5.0p-25, 0x1ef491085fa3c1.0p-79 }, { 0x9b8000.0p-24, 0xff3f8c.0p-25, 0x1d607a7c2b8c53.0p-79 }, { 0x9a8000.0p-24, 0x814697.0p-24, -0x12ad3817004f3f.0p-78 }, { 0x9a0000.0p-24, 0x821b06.0p-24, -0x189fc53117f9e5.0p-81 }, { 0x990000.0p-24, 0x83c5f8.0p-24, 0x14cf15a048907b.0p-79 }, { 0x988000.0p-24, 0x849c7d.0p-24, 0x1cbb1d35fb8287.0p-78 }, { 0x978000.0p-24, 0x864ba6.0p-24, 0x1128639b814f9c.0p-78 }, { 0x970000.0p-24, 0x87244c.0p-24, 0x184733853300f0.0p-79 }, { 0x968000.0p-24, 0x87fdaa.0p-24, 0x109d23aef77dd6.0p-80 }, { 0x958000.0p-24, 0x89b293.0p-24, -0x1a81ef367a59de.0p-78 }, { 0x950000.0p-24, 0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78 }, { 0x948000.0p-24, 0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79 }, { 0x938000.0p-24, 0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79 }, { 0x930000.0p-24, 0x8e03c2.0p-24, 0x135cc00e566f77.0p-78 }, { 0x928000.0p-24, 0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80 }, { 0x918000.0p-24, 0x90a3ee.0p-24, -0x16e171b15433d7.0p-79 }, { 0x910000.0p-24, 0x918587.0p-24, -0x1d050da07f3237.0p-79 }, { 0x908000.0p-24, 0x9267e7.0p-24, 0x1be03669a5268d.0p-79 }, { 0x8f8000.0p-24, 0x942f04.0p-24, 0x10b28e0e26c337.0p-79 }, { 0x8f0000.0p-24, 0x9513c3.0p-24, 0x1a1d820da57cf3.0p-78 }, { 0x8e8000.0p-24, 0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79 }, { 0x8e0000.0p-24, 0x96dfab.0p-24, -0x109e417a6e507c.0p-78 }, { 0x8d0000.0p-24, 0x98aed2.0p-24, 0x10d01a2c5b0e98.0p-79 }, { 0x8c8000.0p-24, 0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78 }, { 0x8c0000.0p-24, 0x9a8145.0p-24, 0x1b3b190b83f952.0p-78 }, { 0x8b8000.0p-24, 0x9b6bbf.0p-24, 0x13a69fad7e7abe.0p-78 }, { 0x8b0000.0p-24, 0x9c5711.0p-24, -0x11cd12316f576b.0p-78 }, { 0x8a8000.0p-24, 0x9d433b.0p-24, 0x1c95c444b807a2.0p-79 }, { 0x898000.0p-24, 0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79 }, { 0x890000.0p-24, 0xa00ce1.0p-24, 0x125ca93186cf0f.0p-81 }, { 0x888000.0p-24, 0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79 }, { 0x880000.0p-24, 0xa1ed00.0p-24, -0x1a0db876613d20.0p-78 }, { 0x878000.0p-24, 0xa2de62.0p-24, 0x193224e8516c01.0p-79 }, { 0x870000.0p-24, 0xa3d0a9.0p-24, 0x1fa28b4d2541ad.0p-79 }, { 0x868000.0p-24, 0xa4c3d6.0p-24, 0x1c1b5760fb4572.0p-78 }, { 0x858000.0p-24, 0xa6acea.0p-24, 0x1fed5d0f65949c.0p-80 }, { 0x850000.0p-24, 0xa7a2d4.0p-24, 0x1ad270c9d74936.0p-80 }, { 0x848000.0p-24, 0xa899ab.0p-24, 0x199ff15ce53266.0p-79 }, { 0x840000.0p-24, 0xa99171.0p-24, 0x1a19e15ccc45d2.0p-79 }, { 0x838000.0p-24, 0xaa8a28.0p-24, -0x121a14ec532b36.0p-80 }, { 0x830000.0p-24, 0xab83d1.0p-24, 0x1aee319980bff3.0p-79 }, { 0x828000.0p-24, 0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80 }, { 0x820000.0p-24, 0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80 }, { 0x818000.0p-24, 0xae768f.0p-24, 0x17c35c55a04a83.0p-81 }, { 0x810000.0p-24, 0xaf7415.0p-24, 0x1448324047019b.0p-78 }, { 0x808000.0p-24, 0xb07298.0p-24, -0x1750ee3915a198.0p-78 }, { 0x800000.0p-24, 0xb17218.0p-24, -0x105c610ca86c39.0p-81 }, }; #ifdef USE_UTAB static const struct { float H; /* 1 + i/INTERVALS (exact) */ float E; /* H(i) * G(i) - 1 (exact) */ } U[TSIZE] = { { 0x800000.0p-23, 0 }, { 0x810000.0p-23, -0x800000.0p-37 }, { 0x820000.0p-23, -0x800000.0p-35 }, { 0x830000.0p-23, -0x900000.0p-34 }, { 0x840000.0p-23, -0x800000.0p-33 }, { 0x850000.0p-23, -0xc80000.0p-33 }, { 0x860000.0p-23, -0xa00000.0p-36 }, { 0x870000.0p-23, 0x940000.0p-33 }, { 0x880000.0p-23, 0x800000.0p-35 }, { 0x890000.0p-23, -0xc80000.0p-34 }, { 0x8a0000.0p-23, 0xe00000.0p-36 }, { 0x8b0000.0p-23, 0x900000.0p-33 }, { 0x8c0000.0p-23, -0x800000.0p-35 }, { 0x8d0000.0p-23, -0xe00000.0p-33 }, { 0x8e0000.0p-23, 0x880000.0p-33 }, { 0x8f0000.0p-23, -0xa80000.0p-34 }, { 0x900000.0p-23, -0x800000.0p-35 }, { 0x910000.0p-23, 0x800000.0p-37 }, { 0x920000.0p-23, 0x900000.0p-35 }, { 0x930000.0p-23, 0xd00000.0p-35 }, { 0x940000.0p-23, 0xe00000.0p-35 }, { 0x950000.0p-23, 0xc00000.0p-35 }, { 0x960000.0p-23, 0xe00000.0p-36 }, { 0x970000.0p-23, -0x800000.0p-38 }, { 0x980000.0p-23, -0xc00000.0p-35 }, { 0x990000.0p-23, -0xd00000.0p-34 }, { 0x9a0000.0p-23, 0x880000.0p-33 }, { 0x9b0000.0p-23, 0xe80000.0p-35 }, { 0x9c0000.0p-23, -0x800000.0p-35 }, { 0x9d0000.0p-23, 0xb40000.0p-33 }, { 0x9e0000.0p-23, 0x880000.0p-34 }, { 0x9f0000.0p-23, -0xe00000.0p-35 }, { 0xa00000.0p-23, 0x800000.0p-33 }, { 0xa10000.0p-23, -0x900000.0p-36 }, { 0xa20000.0p-23, -0xb00000.0p-33 }, { 0xa30000.0p-23, -0xa00000.0p-36 }, { 0xa40000.0p-23, 0x800000.0p-33 }, { 0xa50000.0p-23, -0xf80000.0p-35 }, { 0xa60000.0p-23, 0x880000.0p-34 }, { 0xa70000.0p-23, -0x900000.0p-33 }, { 0xa80000.0p-23, -0x800000.0p-35 }, { 0xa90000.0p-23, 0x900000.0p-34 }, { 0xaa0000.0p-23, 0xa80000.0p-33 }, { 0xab0000.0p-23, -0xac0000.0p-34 }, { 0xac0000.0p-23, -0x800000.0p-37 }, { 0xad0000.0p-23, 0xf80000.0p-35 }, { 0xae0000.0p-23, 0xf80000.0p-34 }, { 0xaf0000.0p-23, -0xac0000.0p-33 }, { 0xb00000.0p-23, -0x800000.0p-33 }, { 0xb10000.0p-23, -0xb80000.0p-34 }, { 0xb20000.0p-23, -0x800000.0p-34 }, { 0xb30000.0p-23, -0xb00000.0p-35 }, { 0xb40000.0p-23, -0x800000.0p-35 }, { 0xb50000.0p-23, -0xe00000.0p-36 }, { 0xb60000.0p-23, -0x800000.0p-35 }, { 0xb70000.0p-23, -0xb00000.0p-35 }, { 0xb80000.0p-23, -0x800000.0p-34 }, { 0xb90000.0p-23, -0xb80000.0p-34 }, { 0xba0000.0p-23, -0x800000.0p-33 }, { 0xbb0000.0p-23, -0xac0000.0p-33 }, { 0xbc0000.0p-23, 0x980000.0p-33 }, { 0xbd0000.0p-23, 0xbc0000.0p-34 }, { 0xbe0000.0p-23, 0xe00000.0p-36 }, { 0xbf0000.0p-23, -0xb80000.0p-35 }, { 0xc00000.0p-23, -0x800000.0p-33 }, { 0xc10000.0p-23, 0xa80000.0p-33 }, { 0xc20000.0p-23, 0x900000.0p-34 }, { 0xc30000.0p-23, -0x800000.0p-35 }, { 0xc40000.0p-23, -0x900000.0p-33 }, { 0xc50000.0p-23, 0x820000.0p-33 }, { 0xc60000.0p-23, 0x800000.0p-38 }, { 0xc70000.0p-23, -0x820000.0p-33 }, { 0xc80000.0p-23, 0x800000.0p-33 }, { 0xc90000.0p-23, -0xa00000.0p-36 }, { 0xca0000.0p-23, -0xb00000.0p-33 }, { 0xcb0000.0p-23, 0x840000.0p-34 }, { 0xcc0000.0p-23, -0xd00000.0p-34 }, { 0xcd0000.0p-23, 0x800000.0p-33 }, { 0xce0000.0p-23, -0xe00000.0p-35 }, { 0xcf0000.0p-23, 0xa60000.0p-33 }, { 0xd00000.0p-23, -0x800000.0p-35 }, { 0xd10000.0p-23, 0xb40000.0p-33 }, { 0xd20000.0p-23, -0x800000.0p-35 }, { 0xd30000.0p-23, 0xaa0000.0p-33 }, { 0xd40000.0p-23, -0xe00000.0p-35 }, { 0xd50000.0p-23, 0x880000.0p-33 }, { 0xd60000.0p-23, -0xd00000.0p-34 }, { 0xd70000.0p-23, 0x9c0000.0p-34 }, { 0xd80000.0p-23, -0xb00000.0p-33 }, { 0xd90000.0p-23, -0x800000.0p-38 }, { 0xda0000.0p-23, 0xa40000.0p-33 }, { 0xdb0000.0p-23, -0xdc0000.0p-34 }, { 0xdc0000.0p-23, 0xc00000.0p-35 }, { 0xdd0000.0p-23, 0xca0000.0p-33 }, { 0xde0000.0p-23, -0xb80000.0p-34 }, { 0xdf0000.0p-23, 0xd00000.0p-35 }, { 0xe00000.0p-23, 0xc00000.0p-33 }, { 0xe10000.0p-23, -0xf40000.0p-34 }, { 0xe20000.0p-23, 0x800000.0p-37 }, { 0xe30000.0p-23, 0x860000.0p-33 }, { 0xe40000.0p-23, -0xc80000.0p-33 }, { 0xe50000.0p-23, -0xa80000.0p-34 }, { 0xe60000.0p-23, 0xe00000.0p-36 }, { 0xe70000.0p-23, 0x880000.0p-33 }, { 0xe80000.0p-23, -0xe00000.0p-33 }, { 0xe90000.0p-23, -0xfc0000.0p-34 }, { 0xea0000.0p-23, -0x800000.0p-35 }, { 0xeb0000.0p-23, 0xe80000.0p-35 }, { 0xec0000.0p-23, 0x900000.0p-33 }, { 0xed0000.0p-23, 0xe20000.0p-33 }, { 0xee0000.0p-23, -0xac0000.0p-33 }, { 0xef0000.0p-23, -0xc80000.0p-34 }, { 0xf00000.0p-23, -0x800000.0p-35 }, { 0xf10000.0p-23, 0x800000.0p-35 }, { 0xf20000.0p-23, 0xb80000.0p-34 }, { 0xf30000.0p-23, 0x940000.0p-33 }, { 0xf40000.0p-23, 0xc80000.0p-33 }, { 0xf50000.0p-23, -0xf20000.0p-33 }, { 0xf60000.0p-23, -0xc80000.0p-33 }, { 0xf70000.0p-23, -0xa20000.0p-33 }, { 0xf80000.0p-23, -0x800000.0p-33 }, { 0xf90000.0p-23, -0xc40000.0p-34 }, { 0xfa0000.0p-23, -0x900000.0p-34 }, { 0xfb0000.0p-23, -0xc80000.0p-35 }, { 0xfc0000.0p-23, -0x800000.0p-35 }, { 0xfd0000.0p-23, -0x900000.0p-36 }, { 0xfe0000.0p-23, -0x800000.0p-37 }, { 0xff0000.0p-23, -0x800000.0p-39 }, { 0x800000.0p-22, 0 }, }; #endif /* USE_UTAB */ #ifdef STRUCT_RETURN #define RETURN1(rp, v) do { \ (rp)->hi = (v); \ (rp)->lo_set = 0; \ return; \ } while (0) #define RETURN2(rp, h, l) do { \ (rp)->hi = (h); \ (rp)->lo = (l); \ (rp)->lo_set = 1; \ return; \ } while (0) struct ld { long double hi; long double lo; int lo_set; }; #else #define RETURN1(rp, v) RETURNF(v) #define RETURN2(rp, h, l) RETURNI((h) + (l)) #endif #ifdef STRUCT_RETURN static inline __always_inline void k_logl(long double x, struct ld *rp) #else long double logl(long double x) #endif { long double d, dk, val_hi, val_lo, z; uint64_t ix, lx; int i, k; uint16_t hx; EXTRACT_LDBL80_WORDS(hx, lx, x); k = -16383; #if 0 /* Hard to do efficiently. Don't do it until we support all modes. */ if (x == 1) RETURN1(rp, 0); /* log(1) = +0 in all rounding modes */ #endif if (hx == 0 || hx >= 0x8000) { /* zero, negative or subnormal? */ if (((hx & 0x7fff) | lx) == 0) RETURN1(rp, -1 / zero); /* log(+-0) = -Inf */ if (hx != 0) /* log(neg or [pseudo-]NaN) = qNaN: */ RETURN1(rp, (x - x) / zero); x *= 0x1.0p65; /* subnormal; scale up x */ /* including pseudo-subnormals */ EXTRACT_LDBL80_WORDS(hx, lx, x); k = -16383 - 65; } else if (hx >= 0x7fff || (lx & 0x8000000000000000ULL) == 0) RETURN1(rp, x + x); /* log(Inf or NaN) = Inf or qNaN */ /* log(pseudo-Inf) = qNaN */ /* log(pseudo-NaN) = qNaN */ /* log(unnormal) = qNaN */ #ifndef STRUCT_RETURN ENTERI(); #endif k += hx; ix = lx & 0x7fffffffffffffffULL; dk = k; /* Scale x to be in [1, 2). */ SET_LDBL_EXPSIGN(x, 0x3fff); /* 0 <= i <= INTERVALS: */ #define L2I (64 - LOG2_INTERVALS) i = (ix + (1LL << (L2I - 2))) >> (L2I - 1); /* * -0.005280 < d < 0.004838. In particular, the infinite- * precision |d| is <= 2**-7. Rounding of G(i) to 8 bits * ensures that d is representable without extra precision for * this bound on |d| (since when this calculation is expressed * as x*G(i)-1, the multiplication needs as many extra bits as * G(i) has and the subtraction cancels 8 bits). But for * most i (107 cases out of 129), the infinite-precision |d| * is <= 2**-8. G(i) is rounded to 9 bits for such i to give * better accuracy (this works by improving the bound on |d|, * which in turn allows rounding to 9 bits in more cases). * This is only important when the original x is near 1 -- it * lets us avoid using a special method to give the desired * accuracy for such x. */ if (0) d = x * G(i) - 1; else { #ifdef USE_UTAB d = (x - H(i)) * G(i) + E(i); #else long double x_hi, x_lo; float fx_hi; /* * Split x into x_hi + x_lo to calculate x*G(i)-1 exactly. * G(i) has at most 9 bits, so the splitting point is not * critical. */ SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000); x_hi = fx_hi; x_lo = x - x_hi; d = x_hi * G(i) - 1 + x_lo * G(i); #endif } /* * Our algorithm depends on exact cancellation of F_lo(i) and * F_hi(i) with dk*ln_2_lo and dk*ln2_hi when k is -1 and i is * at the end of the table. This and other technical complications * make it difficult to avoid the double scaling in (dk*ln2) * * log(base) for base != e without losing more accuracy and/or * efficiency than is gained. */ z = d * d; val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) + (F_lo(i) + dk * ln2_lo + z * d * (d * P4 + P3)) + z * P2; val_hi = d; #ifdef DEBUG if (fetestexcept(FE_UNDERFLOW)) breakpoint(); #endif _3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi); RETURN2(rp, val_hi, val_lo); } long double log1pl(long double x) { long double d, d_hi, d_lo, dk, f_lo, val_hi, val_lo, z; long double f_hi, twopminusk; uint64_t ix, lx; int i, k; int16_t ax, hx; EXTRACT_LDBL80_WORDS(hx, lx, x); if (hx < 0x3fff) { /* x < 1, or x neg NaN */ ax = hx & 0x7fff; if (ax >= 0x3fff) { /* x <= -1, or x neg NaN */ if (ax == 0x3fff && lx == 0x8000000000000000ULL) RETURNF(-1 / zero); /* log1p(-1) = -Inf */ /* log1p(x < 1, or x [pseudo-]NaN) = qNaN: */ RETURNF((x - x) / (x - x)); } if (ax <= 0x3fbe) { /* |x| < 2**-64 */ if ((int)x == 0) RETURNF(x); /* x with inexact if x != 0 */ } f_hi = 1; f_lo = x; } else if (hx >= 0x7fff) { /* x +Inf or non-neg NaN */ RETURNF(x + x); /* log1p(Inf or NaN) = Inf or qNaN */ /* log1p(pseudo-Inf) = qNaN */ /* log1p(pseudo-NaN) = qNaN */ /* log1p(unnormal) = qNaN */ } else if (hx < 0x407f) { /* 1 <= x < 2**128 */ f_hi = x; f_lo = 1; } else { /* 2**128 <= x < +Inf */ f_hi = x; f_lo = 0; /* avoid underflow of the P5 term */ } ENTERI(); x = f_hi + f_lo; f_lo = (f_hi - x) + f_lo; EXTRACT_LDBL80_WORDS(hx, lx, x); k = -16383; k += hx; ix = lx & 0x7fffffffffffffffULL; dk = k; SET_LDBL_EXPSIGN(x, 0x3fff); twopminusk = 1; SET_LDBL_EXPSIGN(twopminusk, 0x7ffe - (hx & 0x7fff)); f_lo *= twopminusk; i = (ix + (1LL << (L2I - 2))) >> (L2I - 1); /* * x*G(i)-1 (with a reduced x) can be represented exactly, as * above, but now we need to evaluate the polynomial on d = * (x+f_lo)*G(i)-1 and extra precision is needed for that. * Since x+x_lo is a hi+lo decomposition and subtracting 1 * doesn't lose too many bits, an inexact calculation for * f_lo*G(i) is good enough. */ if (0) d_hi = x * G(i) - 1; else { #ifdef USE_UTAB d_hi = (x - H(i)) * G(i) + E(i); #else long double x_hi, x_lo; float fx_hi; SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000); x_hi = fx_hi; x_lo = x - x_hi; d_hi = x_hi * G(i) - 1 + x_lo * G(i); #endif } d_lo = f_lo * G(i); /* * This is _2sumF(d_hi, d_lo) inlined. The condition * (d_hi == 0 || |d_hi| >= |d_lo|) for using _2sumF() is not * always satisifed, so it is not clear that this works, but * it works in practice. It works even if it gives a wrong * normalized d_lo, since |d_lo| > |d_hi| implies that i is * nonzero and d is tiny, so the F(i) term dominates d_lo. * In float precision: * (By exhaustive testing, the worst case is d_hi = 0x1.bp-25. * And if d is only a little tinier than that, we would have * another underflow problem for the P3 term; this is also ruled * out by exhaustive testing.) */ d = d_hi + d_lo; d_lo = d_hi - d + d_lo; d_hi = d; z = d * d; val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) + (F_lo(i) + dk * ln2_lo + d_lo + z * d * (d * P4 + P3)) + z * P2; val_hi = d_hi; #ifdef DEBUG if (fetestexcept(FE_UNDERFLOW)) breakpoint(); #endif _3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi); RETURNI(val_hi + val_lo); } #ifdef STRUCT_RETURN long double logl(long double x) { struct ld r; ENTERI(); k_logl(x, &r); RETURNSPI(&r); } /* Use macros since GCC < 8 rejects static const expressions in initializers. */ #define invln10_hi 4.3429448190317999e-1 /* 0x1bcb7b1526e000.0p-54 */ #define invln10_lo 7.1842412889749798e-14 /* 0x1438ca9aadd558.0p-96 */ #define invln2_hi 1.4426950408887933e0 /* 0x171547652b8000.0p-52 */ #define invln2_lo 1.7010652264631490e-13 /* 0x17f0bbbe87fed0.0p-95 */ /* Let the compiler pre-calculate this sum to avoid FE_INEXACT at run time. */ static const double invln10_lo_plus_hi = invln10_lo + invln10_hi; static const double invln2_lo_plus_hi = invln2_lo + invln2_hi; long double log10l(long double x) { struct ld r; long double hi, lo; ENTERI(); k_logl(x, &r); if (!r.lo_set) RETURNI(r.hi); _2sumF(r.hi, r.lo); hi = (float)r.hi; lo = r.lo + (r.hi - hi); RETURNI(invln10_hi * hi + (invln10_lo_plus_hi * lo + invln10_lo * hi)); } long double log2l(long double x) { struct ld r; long double hi, lo; ENTERI(); k_logl(x, &r); if (!r.lo_set) RETURNI(r.hi); _2sumF(r.hi, r.lo); hi = (float)r.hi; lo = r.lo + (r.hi - hi); RETURNI(invln2_hi * hi + (invln2_lo_plus_hi * lo + invln2_lo * hi)); } #endif /* STRUCT_RETURN */ diff --git a/lib/msun/src/catrig.c b/lib/msun/src/catrig.c index 929811a09a3b..45af164a66c5 100644 --- a/lib/msun/src/catrig.c +++ b/lib/msun/src/catrig.c @@ -1,653 +1,652 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2012 Stephen Montgomery-Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "math.h" #include "math_private.h" #undef isinf #define isinf(x) (fabs(x) == INFINITY) #undef isnan #define isnan(x) ((x) != (x)) #define raise_inexact() do { volatile float junk __unused = 1 + tiny; } while(0) #undef signbit #define signbit(x) (__builtin_signbit(x)) /* We need that DBL_EPSILON^2/128 is larger than FOUR_SQRT_MIN. */ static const double A_crossover = 10, /* Hull et al suggest 1.5, but 10 works better */ B_crossover = 0.6417, /* suggested by Hull et al */ FOUR_SQRT_MIN = 0x1p-509, /* >= 4 * sqrt(DBL_MIN) */ QUARTER_SQRT_MAX = 0x1p509, /* <= sqrt(DBL_MAX) / 4 */ m_e = 2.7182818284590452e0, /* 0x15bf0a8b145769.0p-51 */ m_ln2 = 6.9314718055994531e-1, /* 0x162e42fefa39ef.0p-53 */ pio2_hi = 1.5707963267948966e0, /* 0x1921fb54442d18.0p-52 */ RECIP_EPSILON = 1 / DBL_EPSILON, SQRT_3_EPSILON = 2.5809568279517849e-8, /* 0x1bb67ae8584caa.0p-78 */ SQRT_6_EPSILON = 3.6500241499888571e-8, /* 0x13988e1409212e.0p-77 */ SQRT_MIN = 0x1p-511; /* >= sqrt(DBL_MIN) */ static const volatile double pio2_lo = 6.1232339957367659e-17; /* 0x11a62633145c07.0p-106 */ static const volatile float tiny = 0x1p-100; static double complex clog_for_large_values(double complex z); /* * Testing indicates that all these functions are accurate up to 4 ULP. * The functions casin(h) and cacos(h) are about 2.5 times slower than asinh. * The functions catan(h) are a little under 2 times slower than atanh. * * The code for casinh, casin, cacos, and cacosh comes first. The code is * rather complicated, and the four functions are highly interdependent. * * The code for catanh and catan comes at the end. It is much simpler than * the other functions, and the code for these can be disconnected from the * rest of the code. */ /* * ================================ * | casinh, casin, cacos, cacosh | * ================================ */ /* * The algorithm is very close to that in "Implementing the complex arcsine * and arccosine functions using exception handling" by T. E. Hull, Thomas F. * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335, * http://dl.acm.org/citation.cfm?id=275324. * * Throughout we use the convention z = x + I*y. * * casinh(z) = sign(x)*log(A+sqrt(A*A-1)) + I*asin(B) * where * A = (|z+I| + |z-I|) / 2 * B = (|z+I| - |z-I|) / 2 = y/A * * These formulas become numerically unstable: * (a) for Re(casinh(z)) when z is close to the line segment [-I, I] (that * is, Re(casinh(z)) is close to 0); * (b) for Im(casinh(z)) when z is close to either of the intervals * [I, I*infinity) or (-I*infinity, -I] (that is, |Im(casinh(z))| is * close to PI/2). * * These numerical problems are overcome by defining * f(a, b) = (hypot(a, b) - b) / 2 = a*a / (hypot(a, b) + b) / 2 * Then if A < A_crossover, we use * log(A + sqrt(A*A-1)) = log1p((A-1) + sqrt((A-1)*(A+1))) * A-1 = f(x, 1+y) + f(x, 1-y) * and if B > B_crossover, we use * asin(B) = atan2(y, sqrt(A*A - y*y)) = atan2(y, sqrt((A+y)*(A-y))) * A-y = f(x, y+1) + f(x, y-1) * where without loss of generality we have assumed that x and y are * non-negative. * * Much of the difficulty comes because the intermediate computations may * produce overflows or underflows. This is dealt with in the paper by Hull * et al by using exception handling. We do this by detecting when * computations risk underflow or overflow. The hardest part is handling the * underflows when computing f(a, b). * * Note that the function f(a, b) does not appear explicitly in the paper by * Hull et al, but the idea may be found on pages 308 and 309. Introducing the * function f(a, b) allows us to concentrate many of the clever tricks in this * paper into one function. */ /* * Function f(a, b, hypot_a_b) = (hypot(a, b) - b) / 2. * Pass hypot(a, b) as the third argument. */ static inline double f(double a, double b, double hypot_a_b) { if (b < 0) return ((hypot_a_b - b) / 2); if (b == 0) return (a / 2); return (a * a / (hypot_a_b + b) / 2); } /* * All the hard work is contained in this function. * x and y are assumed positive or zero, and less than RECIP_EPSILON. * Upon return: * rx = Re(casinh(z)) = -Im(cacos(y + I*x)). * B_is_usable is set to 1 if the value of B is usable. * If B_is_usable is set to 0, sqrt_A2my2 = sqrt(A*A - y*y), and new_y = y. * If returning sqrt_A2my2 has potential to result in an underflow, it is * rescaled, and new_y is similarly rescaled. */ static inline void do_hard_work(double x, double y, double *rx, int *B_is_usable, double *B, double *sqrt_A2my2, double *new_y) { double R, S, A; /* A, B, R, and S are as in Hull et al. */ double Am1, Amy; /* A-1, A-y. */ R = hypot(x, y + 1); /* |z+I| */ S = hypot(x, y - 1); /* |z-I| */ /* A = (|z+I| + |z-I|) / 2 */ A = (R + S) / 2; /* * Mathematically A >= 1. There is a small chance that this will not * be so because of rounding errors. So we will make certain it is * so. */ if (A < 1) A = 1; if (A < A_crossover) { /* * Am1 = fp + fm, where fp = f(x, 1+y), and fm = f(x, 1-y). * rx = log1p(Am1 + sqrt(Am1*(A+1))) */ if (y == 1 && x < DBL_EPSILON * DBL_EPSILON / 128) { /* * fp is of order x^2, and fm = x/2. * A = 1 (inexactly). */ *rx = sqrt(x); } else if (x >= DBL_EPSILON * fabs(y - 1)) { /* * Underflow will not occur because * x >= DBL_EPSILON^2/128 >= FOUR_SQRT_MIN */ Am1 = f(x, 1 + y, R) + f(x, 1 - y, S); *rx = log1p(Am1 + sqrt(Am1 * (A + 1))); } else if (y < 1) { /* * fp = x*x/(1+y)/4, fm = x*x/(1-y)/4, and * A = 1 (inexactly). */ *rx = x / sqrt((1 - y) * (1 + y)); } else { /* if (y > 1) */ /* * A-1 = y-1 (inexactly). */ *rx = log1p((y - 1) + sqrt((y - 1) * (y + 1))); } } else { *rx = log(A + sqrt(A * A - 1)); } *new_y = y; if (y < FOUR_SQRT_MIN) { /* * Avoid a possible underflow caused by y/A. For casinh this * would be legitimate, but will be picked up by invoking atan2 * later on. For cacos this would not be legitimate. */ *B_is_usable = 0; *sqrt_A2my2 = A * (2 / DBL_EPSILON); *new_y = y * (2 / DBL_EPSILON); return; } /* B = (|z+I| - |z-I|) / 2 = y/A */ *B = y / A; *B_is_usable = 1; if (*B > B_crossover) { *B_is_usable = 0; /* * Amy = fp + fm, where fp = f(x, y+1), and fm = f(x, y-1). * sqrt_A2my2 = sqrt(Amy*(A+y)) */ if (y == 1 && x < DBL_EPSILON / 128) { /* * fp is of order x^2, and fm = x/2. * A = 1 (inexactly). */ *sqrt_A2my2 = sqrt(x) * sqrt((A + y) / 2); } else if (x >= DBL_EPSILON * fabs(y - 1)) { /* * Underflow will not occur because * x >= DBL_EPSILON/128 >= FOUR_SQRT_MIN * and * x >= DBL_EPSILON^2 >= FOUR_SQRT_MIN */ Amy = f(x, y + 1, R) + f(x, y - 1, S); *sqrt_A2my2 = sqrt(Amy * (A + y)); } else if (y > 1) { /* * fp = x*x/(y+1)/4, fm = x*x/(y-1)/4, and * A = y (inexactly). * * y < RECIP_EPSILON. So the following * scaling should avoid any underflow problems. */ *sqrt_A2my2 = x * (4 / DBL_EPSILON / DBL_EPSILON) * y / sqrt((y + 1) * (y - 1)); *new_y = y * (4 / DBL_EPSILON / DBL_EPSILON); } else { /* if (y < 1) */ /* * fm = 1-y >= DBL_EPSILON, fp is of order x^2, and * A = 1 (inexactly). */ *sqrt_A2my2 = sqrt((1 - y) * (1 + y)); } } } /* * casinh(z) = z + O(z^3) as z -> 0 * * casinh(z) = sign(x)*clog(sign(x)*z) + O(1/z^2) as z -> infinity * The above formula works for the imaginary part as well, because * Im(casinh(z)) = sign(x)*atan2(sign(x)*y, fabs(x)) + O(y/z^3) * as z -> infinity, uniformly in y */ double complex casinh(double complex z) { double x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y; int B_is_usable; double complex w; x = creal(z); y = cimag(z); ax = fabs(x); ay = fabs(y); if (isnan(x) || isnan(y)) { /* casinh(+-Inf + I*NaN) = +-Inf + I*NaN */ if (isinf(x)) return (CMPLX(x, y + y)); /* casinh(NaN + I*+-Inf) = opt(+-)Inf + I*NaN */ if (isinf(y)) return (CMPLX(y, x + x)); /* casinh(NaN + I*0) = NaN + I*0 */ if (y == 0) return (CMPLX(x + x, y)); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ return (CMPLX(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { /* clog...() will raise inexact unless x or y is infinite. */ if (signbit(x) == 0) w = clog_for_large_values(z) + m_ln2; else w = clog_for_large_values(-z) + m_ln2; return (CMPLX(copysign(creal(w), x), copysign(cimag(w), y))); } /* Avoid spuriously raising inexact for z = 0. */ if (x == 0 && y == 0) return (z); /* All remaining cases are inexact. */ raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (z); do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y); if (B_is_usable) ry = asin(B); else ry = atan2(new_y, sqrt_A2my2); return (CMPLX(copysign(rx, x), copysign(ry, y))); } /* * casin(z) = reverse(casinh(reverse(z))) * where reverse(x + I*y) = y + I*x = I*conj(z). */ double complex casin(double complex z) { double complex w = casinh(CMPLX(cimag(z), creal(z))); return (CMPLX(cimag(w), creal(w))); } /* * cacos(z) = PI/2 - casin(z) * but do the computation carefully so cacos(z) is accurate when z is * close to 1. * * cacos(z) = PI/2 - z + O(z^3) as z -> 0 * * cacos(z) = -sign(y)*I*clog(z) + O(1/z^2) as z -> infinity * The above formula works for the real part as well, because * Re(cacos(z)) = atan2(fabs(y), x) + O(y/z^3) * as z -> infinity, uniformly in y */ double complex cacos(double complex z) { double x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x; int sx, sy; int B_is_usable; double complex w; x = creal(z); y = cimag(z); sx = signbit(x); sy = signbit(y); ax = fabs(x); ay = fabs(y); if (isnan(x) || isnan(y)) { /* cacos(+-Inf + I*NaN) = NaN + I*opt(-)Inf */ if (isinf(x)) return (CMPLX(y + y, -INFINITY)); /* cacos(NaN + I*+-Inf) = NaN + I*-+Inf */ if (isinf(y)) return (CMPLX(x + x, -y)); /* cacos(0 + I*NaN) = PI/2 + I*NaN with inexact */ if (x == 0) return (CMPLX(pio2_hi + pio2_lo, y + y)); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ return (CMPLX(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { /* clog...() will raise inexact unless x or y is infinite. */ w = clog_for_large_values(z); rx = fabs(cimag(w)); ry = creal(w) + m_ln2; if (sy == 0) ry = -ry; return (CMPLX(rx, ry)); } /* Avoid spuriously raising inexact for z = 1. */ if (x == 1 && y == 0) return (CMPLX(0, -y)); /* All remaining cases are inexact. */ raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (CMPLX(pio2_hi - (x - pio2_lo), -y)); do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x); if (B_is_usable) { if (sx == 0) rx = acos(B); else rx = acos(-B); } else { if (sx == 0) rx = atan2(sqrt_A2mx2, new_x); else rx = atan2(sqrt_A2mx2, -new_x); } if (sy == 0) ry = -ry; return (CMPLX(rx, ry)); } /* * cacosh(z) = I*cacos(z) or -I*cacos(z) * where the sign is chosen so Re(cacosh(z)) >= 0. */ double complex cacosh(double complex z) { double complex w; double rx, ry; w = cacos(z); rx = creal(w); ry = cimag(w); /* cacosh(NaN + I*NaN) = NaN + I*NaN */ if (isnan(rx) && isnan(ry)) return (CMPLX(ry, rx)); /* cacosh(NaN + I*+-Inf) = +Inf + I*NaN */ /* cacosh(+-Inf + I*NaN) = +Inf + I*NaN */ if (isnan(rx)) return (CMPLX(fabs(ry), rx)); /* cacosh(0 + I*NaN) = NaN + I*NaN */ if (isnan(ry)) return (CMPLX(ry, ry)); return (CMPLX(fabs(ry), copysign(rx, cimag(z)))); } /* * Optimized version of clog() for |z| finite and larger than ~RECIP_EPSILON. */ static double complex clog_for_large_values(double complex z) { double x, y; double ax, ay, t; x = creal(z); y = cimag(z); ax = fabs(x); ay = fabs(y); if (ax < ay) { t = ax; ax = ay; ay = t; } /* * Avoid overflow in hypot() when x and y are both very large. * Divide x and y by E, and then add 1 to the logarithm. This * depends on E being larger than sqrt(2), since the return value of * hypot cannot overflow if neither argument is greater in magnitude * than 1/sqrt(2) of the maximum value of the return type. Likewise * this determines the necessary threshold for using this method * (however, actually use 1/2 instead as it is simpler). * * Dividing by E causes an insignificant loss of accuracy; however * this method is still poor since it is uneccessarily slow. */ if (ax > DBL_MAX / 2) return (CMPLX(log(hypot(x / m_e, y / m_e)) + 1, atan2(y, x))); /* * Avoid overflow when x or y is large. Avoid underflow when x or * y is small. */ if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN) return (CMPLX(log(hypot(x, y)), atan2(y, x))); return (CMPLX(log(ax * ax + ay * ay) / 2, atan2(y, x))); } /* * ================= * | catanh, catan | * ================= */ /* * sum_squares(x,y) = x*x + y*y (or just x*x if y*y would underflow). * Assumes x*x and y*y will not overflow. * Assumes x and y are finite. * Assumes y is non-negative. * Assumes fabs(x) >= DBL_EPSILON. */ static inline double sum_squares(double x, double y) { /* Avoid underflow when y is small. */ if (y < SQRT_MIN) return (x * x); return (x * x + y * y); } /* * real_part_reciprocal(x, y) = Re(1/(x+I*y)) = x/(x*x + y*y). * Assumes x and y are not NaN, and one of x and y is larger than * RECIP_EPSILON. We avoid unwarranted underflow. It is important to not use * the code creal(1/z), because the imaginary part may produce an unwanted * underflow. * This is only called in a context where inexact is always raised before * the call, so no effort is made to avoid or force inexact. */ static inline double real_part_reciprocal(double x, double y) { double scale; uint32_t hx, hy; int32_t ix, iy; /* * This code is inspired by the C99 document n1124.pdf, Section G.5.1, * example 2. */ GET_HIGH_WORD(hx, x); ix = hx & 0x7ff00000; GET_HIGH_WORD(hy, y); iy = hy & 0x7ff00000; #define BIAS (DBL_MAX_EXP - 1) /* XXX more guard digits are useful iff there is extra precision. */ #define CUTOFF (DBL_MANT_DIG / 2 + 1) /* just half or 1 guard digit */ if (ix - iy >= CUTOFF << 20 || isinf(x)) return (1 / x); /* +-Inf -> +-0 is special */ if (iy - ix >= CUTOFF << 20) return (x / y / y); /* should avoid double div, but hard */ if (ix <= (BIAS + DBL_MAX_EXP / 2 - CUTOFF) << 20) return (x / (x * x + y * y)); scale = 1; SET_HIGH_WORD(scale, 0x7ff00000 - ix); /* 2**(1-ilogb(x)) */ x *= scale; y *= scale; return (x / (x * x + y * y) * scale); } /* * catanh(z) = log((1+z)/(1-z)) / 2 * = log1p(4*x / |z-1|^2) / 4 * + I * atan2(2*y, (1-x)*(1+x)-y*y) / 2 * * catanh(z) = z + O(z^3) as z -> 0 * * catanh(z) = 1/z + sign(y)*I*PI/2 + O(1/z^3) as z -> infinity * The above formula works for the real part as well, because * Re(catanh(z)) = x/|z|^2 + O(x/z^4) * as z -> infinity, uniformly in x */ double complex catanh(double complex z) { double x, y, ax, ay, rx, ry; x = creal(z); y = cimag(z); ax = fabs(x); ay = fabs(y); /* This helps handle many cases. */ if (y == 0 && ax <= 1) return (CMPLX(atanh(x), y)); /* To ensure the same accuracy as atan(), and to filter out z = 0. */ if (x == 0) return (CMPLX(x, atan(y))); if (isnan(x) || isnan(y)) { /* catanh(+-Inf + I*NaN) = +-0 + I*NaN */ if (isinf(x)) return (CMPLX(copysign(0, x), y + y)); /* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */ if (isinf(y)) return (CMPLX(copysign(0, x), copysign(pio2_hi + pio2_lo, y))); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ return (CMPLX(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) return (CMPLX(real_part_reciprocal(x, y), copysign(pio2_hi + pio2_lo, y))); if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) { /* * z = 0 was filtered out above. All other cases must raise * inexact, but this is the only case that needs to do it * explicitly. */ raise_inexact(); return (z); } if (ax == 1 && ay < DBL_EPSILON) rx = (m_ln2 - log(ay)) / 2; else rx = log1p(4 * ax / sum_squares(ax - 1, ay)) / 4; if (ax == 1) ry = atan2(2, -ay) / 2; else if (ay < DBL_EPSILON) ry = atan2(2 * ay, (1 - ax) * (1 + ax)) / 2; else ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2; return (CMPLX(copysign(rx, x), copysign(ry, y))); } /* * catan(z) = reverse(catanh(reverse(z))) * where reverse(x + I*y) = y + I*x = I*conj(z). */ double complex catan(double complex z) { double complex w = catanh(CMPLX(cimag(z), creal(z))); return (CMPLX(cimag(w), creal(w))); } #if LDBL_MANT_DIG == 53 __weak_reference(cacosh, cacoshl); __weak_reference(cacos, cacosl); __weak_reference(casinh, casinhl); __weak_reference(casin, casinl); __weak_reference(catanh, catanhl); __weak_reference(catan, catanl); #endif diff --git a/lib/msun/src/catrigf.c b/lib/msun/src/catrigf.c index 7feecfc5de38..da90629ec076 100644 --- a/lib/msun/src/catrigf.c +++ b/lib/msun/src/catrigf.c @@ -1,393 +1,392 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2012 Stephen Montgomery-Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * The algorithm is very close to that in "Implementing the complex arcsine * and arccosine functions using exception handling" by T. E. Hull, Thomas F. * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335, * http://dl.acm.org/citation.cfm?id=275324. * * See catrig.c for complete comments. * * XXX comments were removed automatically, and even short ones on the right * of statements were removed (all of them), contrary to normal style. Only * a few comments on the right of declarations remain. */ -#include #include #include #include "math.h" #include "math_private.h" #undef isinf #define isinf(x) (fabsf(x) == INFINITY) #undef isnan #define isnan(x) ((x) != (x)) #define raise_inexact() do { volatile float junk __unused = 1 + tiny; } while(0) #undef signbit #define signbit(x) (__builtin_signbitf(x)) static const float A_crossover = 10, B_crossover = 0.6417, FOUR_SQRT_MIN = 0x1p-61, QUARTER_SQRT_MAX = 0x1p61, m_e = 2.7182818285e0, /* 0xadf854.0p-22 */ m_ln2 = 6.9314718056e-1, /* 0xb17218.0p-24 */ pio2_hi = 1.5707962513e0, /* 0xc90fda.0p-23 */ RECIP_EPSILON = 1 / FLT_EPSILON, SQRT_3_EPSILON = 5.9801995673e-4, /* 0x9cc471.0p-34 */ SQRT_6_EPSILON = 8.4572793338e-4, /* 0xddb3d7.0p-34 */ SQRT_MIN = 0x1p-63; static const volatile float pio2_lo = 7.5497899549e-8, /* 0xa22169.0p-47 */ tiny = 0x1p-100; static float complex clog_for_large_values(float complex z); static inline float f(float a, float b, float hypot_a_b) { if (b < 0) return ((hypot_a_b - b) / 2); if (b == 0) return (a / 2); return (a * a / (hypot_a_b + b) / 2); } static inline void do_hard_work(float x, float y, float *rx, int *B_is_usable, float *B, float *sqrt_A2my2, float *new_y) { float R, S, A; float Am1, Amy; R = hypotf(x, y + 1); S = hypotf(x, y - 1); A = (R + S) / 2; if (A < 1) A = 1; if (A < A_crossover) { if (y == 1 && x < FLT_EPSILON * FLT_EPSILON / 128) { *rx = sqrtf(x); } else if (x >= FLT_EPSILON * fabsf(y - 1)) { Am1 = f(x, 1 + y, R) + f(x, 1 - y, S); *rx = log1pf(Am1 + sqrtf(Am1 * (A + 1))); } else if (y < 1) { *rx = x / sqrtf((1 - y) * (1 + y)); } else { *rx = log1pf((y - 1) + sqrtf((y - 1) * (y + 1))); } } else { *rx = logf(A + sqrtf(A * A - 1)); } *new_y = y; if (y < FOUR_SQRT_MIN) { *B_is_usable = 0; *sqrt_A2my2 = A * (2 / FLT_EPSILON); *new_y = y * (2 / FLT_EPSILON); return; } *B = y / A; *B_is_usable = 1; if (*B > B_crossover) { *B_is_usable = 0; if (y == 1 && x < FLT_EPSILON / 128) { *sqrt_A2my2 = sqrtf(x) * sqrtf((A + y) / 2); } else if (x >= FLT_EPSILON * fabsf(y - 1)) { Amy = f(x, y + 1, R) + f(x, y - 1, S); *sqrt_A2my2 = sqrtf(Amy * (A + y)); } else if (y > 1) { *sqrt_A2my2 = x * (4 / FLT_EPSILON / FLT_EPSILON) * y / sqrtf((y + 1) * (y - 1)); *new_y = y * (4 / FLT_EPSILON / FLT_EPSILON); } else { *sqrt_A2my2 = sqrtf((1 - y) * (1 + y)); } } } float complex casinhf(float complex z) { float x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y; int B_is_usable; float complex w; x = crealf(z); y = cimagf(z); ax = fabsf(x); ay = fabsf(y); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXF(x, y + y)); if (isinf(y)) return (CMPLXF(y, x + x)); if (y == 0) return (CMPLXF(x + x, y)); return (CMPLXF(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { if (signbit(x) == 0) w = clog_for_large_values(z) + m_ln2; else w = clog_for_large_values(-z) + m_ln2; return (CMPLXF(copysignf(crealf(w), x), copysignf(cimagf(w), y))); } if (x == 0 && y == 0) return (z); raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (z); do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y); if (B_is_usable) ry = asinf(B); else ry = atan2f(new_y, sqrt_A2my2); return (CMPLXF(copysignf(rx, x), copysignf(ry, y))); } float complex casinf(float complex z) { float complex w = casinhf(CMPLXF(cimagf(z), crealf(z))); return (CMPLXF(cimagf(w), crealf(w))); } float complex cacosf(float complex z) { float x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x; int sx, sy; int B_is_usable; float complex w; x = crealf(z); y = cimagf(z); sx = signbit(x); sy = signbit(y); ax = fabsf(x); ay = fabsf(y); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXF(y + y, -INFINITY)); if (isinf(y)) return (CMPLXF(x + x, -y)); if (x == 0) return (CMPLXF(pio2_hi + pio2_lo, y + y)); return (CMPLXF(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { w = clog_for_large_values(z); rx = fabsf(cimagf(w)); ry = crealf(w) + m_ln2; if (sy == 0) ry = -ry; return (CMPLXF(rx, ry)); } if (x == 1 && y == 0) return (CMPLXF(0, -y)); raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (CMPLXF(pio2_hi - (x - pio2_lo), -y)); do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x); if (B_is_usable) { if (sx == 0) rx = acosf(B); else rx = acosf(-B); } else { if (sx == 0) rx = atan2f(sqrt_A2mx2, new_x); else rx = atan2f(sqrt_A2mx2, -new_x); } if (sy == 0) ry = -ry; return (CMPLXF(rx, ry)); } float complex cacoshf(float complex z) { float complex w; float rx, ry; w = cacosf(z); rx = crealf(w); ry = cimagf(w); if (isnan(rx) && isnan(ry)) return (CMPLXF(ry, rx)); if (isnan(rx)) return (CMPLXF(fabsf(ry), rx)); if (isnan(ry)) return (CMPLXF(ry, ry)); return (CMPLXF(fabsf(ry), copysignf(rx, cimagf(z)))); } static float complex clog_for_large_values(float complex z) { float x, y; float ax, ay, t; x = crealf(z); y = cimagf(z); ax = fabsf(x); ay = fabsf(y); if (ax < ay) { t = ax; ax = ay; ay = t; } if (ax > FLT_MAX / 2) return (CMPLXF(logf(hypotf(x / m_e, y / m_e)) + 1, atan2f(y, x))); if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN) return (CMPLXF(logf(hypotf(x, y)), atan2f(y, x))); return (CMPLXF(logf(ax * ax + ay * ay) / 2, atan2f(y, x))); } static inline float sum_squares(float x, float y) { if (y < SQRT_MIN) return (x * x); return (x * x + y * y); } static inline float real_part_reciprocal(float x, float y) { float scale; uint32_t hx, hy; int32_t ix, iy; GET_FLOAT_WORD(hx, x); ix = hx & 0x7f800000; GET_FLOAT_WORD(hy, y); iy = hy & 0x7f800000; #define BIAS (FLT_MAX_EXP - 1) #define CUTOFF (FLT_MANT_DIG / 2 + 1) if (ix - iy >= CUTOFF << 23 || isinf(x)) return (1 / x); if (iy - ix >= CUTOFF << 23) return (x / y / y); if (ix <= (BIAS + FLT_MAX_EXP / 2 - CUTOFF) << 23) return (x / (x * x + y * y)); SET_FLOAT_WORD(scale, 0x7f800000 - ix); x *= scale; y *= scale; return (x / (x * x + y * y) * scale); } float complex catanhf(float complex z) { float x, y, ax, ay, rx, ry; x = crealf(z); y = cimagf(z); ax = fabsf(x); ay = fabsf(y); if (y == 0 && ax <= 1) return (CMPLXF(atanhf(x), y)); if (x == 0) return (CMPLXF(x, atanf(y))); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXF(copysignf(0, x), y + y)); if (isinf(y)) return (CMPLXF(copysignf(0, x), copysignf(pio2_hi + pio2_lo, y))); return (CMPLXF(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) return (CMPLXF(real_part_reciprocal(x, y), copysignf(pio2_hi + pio2_lo, y))); if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) { raise_inexact(); return (z); } if (ax == 1 && ay < FLT_EPSILON) rx = (m_ln2 - logf(ay)) / 2; else rx = log1pf(4 * ax / sum_squares(ax - 1, ay)) / 4; if (ax == 1) ry = atan2f(2, -ay) / 2; else if (ay < FLT_EPSILON) ry = atan2f(2 * ay, (1 - ax) * (1 + ax)) / 2; else ry = atan2f(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2; return (CMPLXF(copysignf(rx, x), copysignf(ry, y))); } float complex catanf(float complex z) { float complex w = catanhf(CMPLXF(cimagf(z), crealf(z))); return (CMPLXF(cimagf(w), crealf(w))); } diff --git a/lib/msun/src/catrigl.c b/lib/msun/src/catrigl.c index 7cc3c1431731..faf9d299670e 100644 --- a/lib/msun/src/catrigl.c +++ b/lib/msun/src/catrigl.c @@ -1,415 +1,414 @@ /*- * Copyright (c) 2012 Stephen Montgomery-Smith * Copyright (c) 2017 Mahdi Mokhtari * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * The algorithm is very close to that in "Implementing the complex arcsine * and arccosine functions using exception handling" by T. E. Hull, Thomas F. * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335, * http://dl.acm.org/citation.cfm?id=275324. * * See catrig.c for complete comments. * * XXX comments were removed automatically, and even short ones on the right * of statements were removed (all of them), contrary to normal style. Only * a few comments on the right of declarations remain. */ -#include #include #include #include "invtrig.h" #include "math.h" #include "math_private.h" #undef isinf #define isinf(x) (fabsl(x) == INFINITY) #undef isnan #define isnan(x) ((x) != (x)) #define raise_inexact() do { volatile float junk __unused = 1 + tiny; } while(0) #undef signbit #define signbit(x) (__builtin_signbitl(x)) #if LDBL_MAX_EXP != 0x4000 #error "Unsupported long double format" #endif static const long double A_crossover = 10, B_crossover = 0.6417, FOUR_SQRT_MIN = 0x1p-8189L, HALF_MAX = 0x1p16383L, QUARTER_SQRT_MAX = 0x1p8189L, RECIP_EPSILON = 1 / LDBL_EPSILON, SQRT_MIN = 0x1p-8191L; #if LDBL_MANT_DIG == 64 static const union IEEEl2bits um_e = LD80C(0xadf85458a2bb4a9b, 1, 2.71828182845904523536e+0L), um_ln2 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L); #define m_e um_e.e #define m_ln2 um_ln2.e static const long double /* The next 2 literals for non-i386. Misrounding them on i386 is harmless. */ SQRT_3_EPSILON = 5.70316273435758915310e-10, /* 0x9cc470a0490973e8.0p-94 */ SQRT_6_EPSILON = 8.06549008734932771664e-10; /* 0xddb3d742c265539e.0p-94 */ #elif LDBL_MANT_DIG == 113 static const long double m_e = 2.71828182845904523536028747135266250e0L, /* 0x15bf0a8b1457695355fb8ac404e7a.0p-111 */ m_ln2 = 6.93147180559945309417232121458176568e-1L, /* 0x162e42fefa39ef35793c7673007e6.0p-113 */ SQRT_3_EPSILON = 2.40370335797945490975336727199878124e-17, /* 0x1bb67ae8584caa73b25742d7078b8.0p-168 */ SQRT_6_EPSILON = 3.39934988877629587239082586223300391e-17; /* 0x13988e1409212e7d0321914321a55.0p-167 */ #else #error "Unsupported long double format" #endif static const volatile float tiny = 0x1p-100; static long double complex clog_for_large_values(long double complex z); static inline long double f(long double a, long double b, long double hypot_a_b) { if (b < 0) return ((hypot_a_b - b) / 2); if (b == 0) return (a / 2); return (a * a / (hypot_a_b + b) / 2); } static inline void do_hard_work(long double x, long double y, long double *rx, int *B_is_usable, long double *B, long double *sqrt_A2my2, long double *new_y) { long double R, S, A; long double Am1, Amy; R = hypotl(x, y + 1); S = hypotl(x, y - 1); A = (R + S) / 2; if (A < 1) A = 1; if (A < A_crossover) { if (y == 1 && x < LDBL_EPSILON * LDBL_EPSILON / 128) { *rx = sqrtl(x); } else if (x >= LDBL_EPSILON * fabsl(y - 1)) { Am1 = f(x, 1 + y, R) + f(x, 1 - y, S); *rx = log1pl(Am1 + sqrtl(Am1 * (A + 1))); } else if (y < 1) { *rx = x / sqrtl((1 - y) * (1 + y)); } else { *rx = log1pl((y - 1) + sqrtl((y - 1) * (y + 1))); } } else { *rx = logl(A + sqrtl(A * A - 1)); } *new_y = y; if (y < FOUR_SQRT_MIN) { *B_is_usable = 0; *sqrt_A2my2 = A * (2 / LDBL_EPSILON); *new_y = y * (2 / LDBL_EPSILON); return; } *B = y / A; *B_is_usable = 1; if (*B > B_crossover) { *B_is_usable = 0; if (y == 1 && x < LDBL_EPSILON / 128) { *sqrt_A2my2 = sqrtl(x) * sqrtl((A + y) / 2); } else if (x >= LDBL_EPSILON * fabsl(y - 1)) { Amy = f(x, y + 1, R) + f(x, y - 1, S); *sqrt_A2my2 = sqrtl(Amy * (A + y)); } else if (y > 1) { *sqrt_A2my2 = x * (4 / LDBL_EPSILON / LDBL_EPSILON) * y / sqrtl((y + 1) * (y - 1)); *new_y = y * (4 / LDBL_EPSILON / LDBL_EPSILON); } else { *sqrt_A2my2 = sqrtl((1 - y) * (1 + y)); } } } long double complex casinhl(long double complex z) { long double x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y; int B_is_usable; long double complex w; x = creall(z); y = cimagl(z); ax = fabsl(x); ay = fabsl(y); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXL(x, y + y)); if (isinf(y)) return (CMPLXL(y, x + x)); if (y == 0) return (CMPLXL(x + x, y)); return (CMPLXL(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { if (signbit(x) == 0) w = clog_for_large_values(z) + m_ln2; else w = clog_for_large_values(-z) + m_ln2; return (CMPLXL(copysignl(creall(w), x), copysignl(cimagl(w), y))); } if (x == 0 && y == 0) return (z); raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (z); do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y); if (B_is_usable) ry = asinl(B); else ry = atan2l(new_y, sqrt_A2my2); return (CMPLXL(copysignl(rx, x), copysignl(ry, y))); } long double complex casinl(long double complex z) { long double complex w; w = casinhl(CMPLXL(cimagl(z), creall(z))); return (CMPLXL(cimagl(w), creall(w))); } long double complex cacosl(long double complex z) { long double x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x; int sx, sy; int B_is_usable; long double complex w; x = creall(z); y = cimagl(z); sx = signbit(x); sy = signbit(y); ax = fabsl(x); ay = fabsl(y); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXL(y + y, -INFINITY)); if (isinf(y)) return (CMPLXL(x + x, -y)); if (x == 0) return (CMPLXL(pio2_hi + pio2_lo, y + y)); return (CMPLXL(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { w = clog_for_large_values(z); rx = fabsl(cimagl(w)); ry = creall(w) + m_ln2; if (sy == 0) ry = -ry; return (CMPLXL(rx, ry)); } if (x == 1 && y == 0) return (CMPLXL(0, -y)); raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) return (CMPLXL(pio2_hi - (x - pio2_lo), -y)); do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x); if (B_is_usable) { if (sx == 0) rx = acosl(B); else rx = acosl(-B); } else { if (sx == 0) rx = atan2l(sqrt_A2mx2, new_x); else rx = atan2l(sqrt_A2mx2, -new_x); } if (sy == 0) ry = -ry; return (CMPLXL(rx, ry)); } long double complex cacoshl(long double complex z) { long double complex w; long double rx, ry; w = cacosl(z); rx = creall(w); ry = cimagl(w); if (isnan(rx) && isnan(ry)) return (CMPLXL(ry, rx)); if (isnan(rx)) return (CMPLXL(fabsl(ry), rx)); if (isnan(ry)) return (CMPLXL(ry, ry)); return (CMPLXL(fabsl(ry), copysignl(rx, cimagl(z)))); } static long double complex clog_for_large_values(long double complex z) { long double x, y; long double ax, ay, t; x = creall(z); y = cimagl(z); ax = fabsl(x); ay = fabsl(y); if (ax < ay) { t = ax; ax = ay; ay = t; } if (ax > HALF_MAX) return (CMPLXL(logl(hypotl(x / m_e, y / m_e)) + 1, atan2l(y, x))); if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN) return (CMPLXL(logl(hypotl(x, y)), atan2l(y, x))); return (CMPLXL(logl(ax * ax + ay * ay) / 2, atan2l(y, x))); } static inline long double sum_squares(long double x, long double y) { if (y < SQRT_MIN) return (x * x); return (x * x + y * y); } static inline long double real_part_reciprocal(long double x, long double y) { long double scale; uint16_t hx, hy; int16_t ix, iy; GET_LDBL_EXPSIGN(hx, x); ix = hx & 0x7fff; GET_LDBL_EXPSIGN(hy, y); iy = hy & 0x7fff; #define BIAS (LDBL_MAX_EXP - 1) #define CUTOFF (LDBL_MANT_DIG / 2 + 1) if (ix - iy >= CUTOFF || isinf(x)) return (1 / x); if (iy - ix >= CUTOFF) return (x / y / y); if (ix <= BIAS + LDBL_MAX_EXP / 2 - CUTOFF) return (x / (x * x + y * y)); scale = 1; SET_LDBL_EXPSIGN(scale, 0x7fff - ix); x *= scale; y *= scale; return (x / (x * x + y * y) * scale); } long double complex catanhl(long double complex z) { long double x, y, ax, ay, rx, ry; x = creall(z); y = cimagl(z); ax = fabsl(x); ay = fabsl(y); if (y == 0 && ax <= 1) return (CMPLXL(atanhl(x), y)); if (x == 0) return (CMPLXL(x, atanl(y))); if (isnan(x) || isnan(y)) { if (isinf(x)) return (CMPLXL(copysignl(0, x), y + y)); if (isinf(y)) return (CMPLXL(copysignl(0, x), copysignl(pio2_hi + pio2_lo, y))); return (CMPLXL(nan_mix(x, y), nan_mix(x, y))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) return (CMPLXL(real_part_reciprocal(x, y), copysignl(pio2_hi + pio2_lo, y))); if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) { raise_inexact(); return (z); } if (ax == 1 && ay < LDBL_EPSILON) rx = (m_ln2 - logl(ay)) / 2; else rx = log1pl(4 * ax / sum_squares(ax - 1, ay)) / 4; if (ax == 1) ry = atan2l(2, -ay) / 2; else if (ay < LDBL_EPSILON) ry = atan2l(2 * ay, (1 - ax) * (1 + ax)) / 2; else ry = atan2l(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2; return (CMPLXL(copysignl(rx, x), copysignl(ry, y))); } long double complex catanl(long double complex z) { long double complex w; w = catanhl(CMPLXL(cimagl(z), creall(z))); return (CMPLXL(cimagl(w), creall(w))); } diff --git a/lib/msun/src/e_acos.c b/lib/msun/src/e_acos.c index 275d0ebb7756..021245667728 100644 --- a/lib/msun/src/e_acos.c +++ b/lib/msun/src/e_acos.c @@ -1,109 +1,108 @@ /* @(#)e_acos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* acos(x) * Method : * acos(x) = pi/2 - asin(x) * acos(-x) = pi/2 + asin(x) * For |x|<=0.5 * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) * For x>0.5 * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) * = 2asin(sqrt((1-x)/2)) * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) * = 2f + (2c + 2s*z*R(z)) * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term * for f so that f+c ~ sqrt(z). * For x<-0.5 * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * * Function needed: sqrt */ #include #include "math.h" #include "math_private.h" static const double one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ pio2_hi = 1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */ static volatile double pio2_lo = 6.12323399573676603587e-17; /* 0x3C91A626, 0x33145C07 */ static const double pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ double acos(double x) { double z,p,q,r,w,s,c,df; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x3ff00000) { /* |x| >= 1 */ u_int32_t lx; GET_LOW_WORD(lx,x); if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */ if(hx>0) return 0.0; /* acos(1) = 0 */ else return pi+2.0*pio2_lo; /* acos(-1)= pi */ } return (x-x)/(x-x); /* acos(|x|>1) is NaN */ } if(ix<0x3fe00000) { /* |x| < 0.5 */ if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ z = x*x; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); r = p/q; return pio2_hi - (x - (pio2_lo-x*r)); } else if (hx<0) { /* x < -0.5 */ z = (one+x)*0.5; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); s = sqrt(z); r = p/q; w = r*s-pio2_lo; return pi - 2.0*(s+w); } else { /* x > 0.5 */ z = (one-x)*0.5; s = sqrt(z); df = s; SET_LOW_WORD(df,0); c = (z-df*df)/(s+df); p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); r = p/q; w = r*s+c; return 2.0*(df+w); } } #if LDBL_MANT_DIG == 53 __weak_reference(acos, acosl); #endif diff --git a/lib/msun/src/e_acosf.c b/lib/msun/src/e_acosf.c index 29f6d4a78495..42ba126d1baa 100644 --- a/lib/msun/src/e_acosf.c +++ b/lib/msun/src/e_acosf.c @@ -1,75 +1,74 @@ /* e_acosf.c -- float version of e_acos.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0000000000e+00, /* 0x3F800000 */ pi = 3.1415925026e+00, /* 0x40490fda */ pio2_hi = 1.5707962513e+00; /* 0x3fc90fda */ static volatile float pio2_lo = 7.5497894159e-08; /* 0x33a22168 */ static const float pS0 = 1.6666586697e-01, pS1 = -4.2743422091e-02, pS2 = -8.6563630030e-03, qS1 = -7.0662963390e-01; float acosf(float x) { float z,p,q,r,w,s,c,df; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x3f800000) { /* |x| >= 1 */ if(ix==0x3f800000) { /* |x| == 1 */ if(hx>0) return 0.0; /* acos(1) = 0 */ else return pi+(float)2.0*pio2_lo; /* acos(-1)= pi */ } return (x-x)/(x-x); /* acos(|x|>1) is NaN */ } if(ix<0x3f000000) { /* |x| < 0.5 */ if(ix<=0x32800000) return pio2_hi+pio2_lo;/*if|x|<2**-26*/ z = x*x; p = z*(pS0+z*(pS1+z*pS2)); q = one+z*qS1; r = p/q; return pio2_hi - (x - (pio2_lo-x*r)); } else if (hx<0) { /* x < -0.5 */ z = (one+x)*(float)0.5; p = z*(pS0+z*(pS1+z*pS2)); q = one+z*qS1; s = sqrtf(z); r = p/q; w = r*s-pio2_lo; return pi - (float)2.0*(s+w); } else { /* x > 0.5 */ int32_t idf; z = (one-x)*(float)0.5; s = sqrtf(z); df = s; GET_FLOAT_WORD(idf,df); SET_FLOAT_WORD(df,idf&0xfffff000); c = (z-df*df)/(s+df); p = z*(pS0+z*(pS1+z*pS2)); q = one+z*qS1; r = p/q; w = r*s+c; return (float)2.0*(df+w); } } diff --git a/lib/msun/src/e_acosh.c b/lib/msun/src/e_acosh.c index d50f5513ee59..31400c473cec 100644 --- a/lib/msun/src/e_acosh.c +++ b/lib/msun/src/e_acosh.c @@ -1,66 +1,65 @@ /* @(#)e_acosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* acosh(x) * Method : * Based on * acosh(x) = log [ x + sqrt(x*x-1) ] * we have * acosh(x) := log(x)+ln2, if x is large; else * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. * * Special cases: * acosh(x) is NaN with signal if x<1. * acosh(NaN) is NaN without signal. */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ double acosh(double x) { double t; int32_t hx; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); if(hx<0x3ff00000) { /* x < 1 */ return (x-x)/(x-x); } else if(hx >=0x41b00000) { /* x > 2**28 */ if(hx >=0x7ff00000) { /* x is inf of NaN */ return x+x; } else return log(x)+ln2; /* acosh(huge)=log(2x) */ } else if(((hx-0x3ff00000)|lx)==0) { return 0.0; /* acosh(1) = 0 */ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ t=x*x; return log(2.0*x-one/(x+sqrt(t-one))); } else { /* 1 #include "math.h" #include "math_private.h" static const float one = 1.0, ln2 = 6.9314718246e-01; /* 0x3f317218 */ float acoshf(float x) { float t; int32_t hx; GET_FLOAT_WORD(hx,x); if(hx<0x3f800000) { /* x < 1 */ return (x-x)/(x-x); } else if(hx >=0x4d800000) { /* x > 2**28 */ if(hx >=0x7f800000) { /* x is inf of NaN */ return x+x; } else return logf(x)+ln2; /* acosh(huge)=log(2x) */ } else if (hx==0x3f800000) { return 0.0; /* acosh(1) = 0 */ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ t=x*x; return logf((float)2.0*x-one/(x+sqrtf(t-one))); } else { /* 1 /* * See e_acosh.c for complete comments. * * Converted to long double by David Schultz and * Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" /* EXP_LARGE is the threshold above which we use acosh(x) ~= log(2x). */ #if LDBL_MANT_DIG == 64 #define EXP_LARGE 34 #elif LDBL_MANT_DIG == 113 #define EXP_LARGE 58 #else #error "Unsupported long double format" #endif #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const double one = 1.0; #if LDBL_MANT_DIG == 64 static const union IEEEl2bits u_ln2 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L); #define ln2 u_ln2.e #elif LDBL_MANT_DIG == 113 static const long double ln2 = 6.93147180559945309417232121458176568e-1L; /* 0x162e42fefa39ef35793c7673007e6.0p-113 */ #else #error "Unsupported long double format" #endif long double acoshl(long double x) { long double t; int16_t hx; ENTERI(); GET_LDBL_EXPSIGN(hx, x); if (hx < 0x3fff) { /* x < 1, or misnormal */ RETURNI((x-x)/(x-x)); } else if (hx >= BIAS + EXP_LARGE) { /* x >= LARGE */ if (hx >= 0x7fff) { /* x is inf, NaN or misnormal */ RETURNI(x+x); } else RETURNI(logl(x)+ln2); /* acosh(huge)=log(2x), or misnormal */ } else if (hx == 0x3fff && x == 1) { RETURNI(0.0); /* acosh(1) = 0 */ } else if (hx >= 0x4000) { /* LARGE > x >= 2, or misnormal */ t=x*x; RETURNI(logl(2.0*x-one/(x+sqrtl(t-one)))); } else { /* 1 /* * See comments in e_acos.c. * Converted to long double by David Schultz . */ #include #include "invtrig.h" #include "math.h" #include "math_private.h" static const long double one= 1.00000000000000000000e+00; #ifdef __i386__ /* XXX Work around the fact that gcc truncates long double constants on i386 */ static volatile double pi1 = 3.14159265358979311600e+00, /* 0x1.921fb54442d18p+1 */ pi2 = 1.22514845490862001043e-16; /* 0x1.1a80000000000p-53 */ #define pi ((long double)pi1 + pi2) #else static const long double pi = 3.14159265358979323846264338327950280e+00L; #endif long double acosl(long double x) { union IEEEl2bits u; long double z,p,q,r,w,s,c,df; int16_t expsign, expt; u.e = x; expsign = u.xbits.expsign; expt = expsign & 0x7fff; if(expt >= BIAS) { /* |x| >= 1 */ if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) { if (expsign>0) return 0.0; /* acos(1) = 0 */ else return pi+2.0*pio2_lo; /* acos(-1)= pi */ } return (x-x)/(x-x); /* acos(|x|>1) is NaN */ } if(expt 0.5 */ z = (one-x)*0.5; s = sqrtl(z); u.e = s; u.bits.manl = 0; df = u.e; c = (z-df*df)/(s+df); p = P(z); q = Q(z); r = p/q; w = r*s+c; return 2.0*(df+w); } } diff --git a/lib/msun/src/e_asin.c b/lib/msun/src/e_asin.c index ae6e496850e1..6662f95faccc 100644 --- a/lib/msun/src/e_asin.c +++ b/lib/msun/src/e_asin.c @@ -1,115 +1,114 @@ /* @(#)e_asin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* asin(x) * Method : * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... * we approximate asin(x) on [0,0.5] by * asin(x) = x + x*x^2*R(x^2) * where * R(x^2) is a rational approximation of (asin(x)-x)/x^3 * and its remez error is bounded by * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) * * For x in [0.5,1] * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; * then for x>0.98 * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) * For x<=0.98, let pio4_hi = pio2_hi/2, then * f = hi part of s; * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) * and * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * */ #include #include "math.h" #include "math_private.h" static const double one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ huge = 1.000e+300, pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ /* coefficient for R(x^2) */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ double asin(double x) { double t=0.0,w,p,q,c,r,s; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>= 0x3ff00000) { /* |x|>= 1 */ u_int32_t lx; GET_LOW_WORD(lx,x); if(((ix-0x3ff00000)|lx)==0) /* asin(1)=+-pi/2 with inexact */ return x*pio2_hi+x*pio2_lo; return (x-x)/(x-x); /* asin(|x|>1) is NaN */ } else if (ix<0x3fe00000) { /* |x|<0.5 */ if(ix<0x3e500000) { /* if |x| < 2**-26 */ if(huge+x>one) return x;/* return x with inexact if x!=0*/ } t = x*x; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); w = p/q; return x+x*w; } /* 1> |x|>= 0.5 */ w = one-fabs(x); t = w*0.5; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); s = sqrt(t); if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ w = p/q; t = pio2_hi-(2.0*(s+s*w)-pio2_lo); } else { w = s; SET_LOW_WORD(w,0); c = (t-w*w)/(s+w); r = p/q; p = 2.0*s*r-(pio2_lo-2.0*c); q = pio4_hi-2.0*w; t = pio4_hi-(p-q); } if(hx>0) return t; else return -t; } #if LDBL_MANT_DIG == 53 __weak_reference(asin, asinl); #endif diff --git a/lib/msun/src/e_asinf.c b/lib/msun/src/e_asinf.c index 391c15870f84..a2ee1a166f03 100644 --- a/lib/msun/src/e_asinf.c +++ b/lib/msun/src/e_asinf.c @@ -1,63 +1,62 @@ /* e_asinf.c -- float version of e_asin.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0000000000e+00, /* 0x3F800000 */ huge = 1.000e+30, /* coefficient for R(x^2) */ pS0 = 1.6666586697e-01, pS1 = -4.2743422091e-02, pS2 = -8.6563630030e-03, qS1 = -7.0662963390e-01; static const double pio2 = 1.570796326794896558e+00; float asinf(float x) { double s; float t,w,p,q; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x3f800000) { /* |x| >= 1 */ if(ix==0x3f800000) /* |x| == 1 */ return x*pio2; /* asin(+-1) = +-pi/2 with inexact */ return (x-x)/(x-x); /* asin(|x|>1) is NaN */ } else if (ix<0x3f000000) { /* |x|<0.5 */ if(ix<0x39800000) { /* |x| < 2**-12 */ if(huge+x>one) return x;/* return x with inexact if x!=0*/ } t = x*x; p = t*(pS0+t*(pS1+t*pS2)); q = one+t*qS1; w = p/q; return x+x*w; } /* 1> |x|>= 0.5 */ w = one-fabsf(x); t = w*(float)0.5; p = t*(pS0+t*(pS1+t*pS2)); q = one+t*qS1; s = sqrt(t); w = p/q; t = pio2-2.0*(s+s*w); if(hx>0) return t; else return -t; } diff --git a/lib/msun/src/e_asinl.c b/lib/msun/src/e_asinl.c index d0cff2f536fa..e73ed1c3a4f0 100644 --- a/lib/msun/src/e_asinl.c +++ b/lib/msun/src/e_asinl.c @@ -1,75 +1,74 @@ /* @(#)e_asin.c 1.3 95/01/18 */ /* FreeBSD: head/lib/msun/src/e_asin.c 176451 2008-02-22 02:30:36Z das */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See comments in e_asin.c. * Converted to long double by David Schultz . */ #include #include "invtrig.h" #include "math.h" #include "math_private.h" static const long double one = 1.00000000000000000000e+00, huge = 1.000e+300; long double asinl(long double x) { union IEEEl2bits u; long double t=0.0,w,p,q,c,r,s; int16_t expsign, expt; u.e = x; expsign = u.xbits.expsign; expt = expsign & 0x7fff; if(expt >= BIAS) { /* |x|>= 1 */ if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) /* asin(1)=+-pi/2 with inexact */ return x*pio2_hi+x*pio2_lo; return (x-x)/(x-x); /* asin(|x|>1) is NaN */ } else if (exptone) return x;/* return x with inexact if x!=0*/ } t = x*x; p = P(t); q = Q(t); w = p/q; return x+x*w; } /* 1> |x|>= 0.5 */ w = one-fabsl(x); t = w*0.5; p = P(t); q = Q(t); s = sqrtl(t); if(u.bits.manh>=THRESH) { /* if |x| is close to 1 */ w = p/q; t = pio2_hi-(2.0*(s+s*w)-pio2_lo); } else { u.e = s; u.bits.manl = 0; w = u.e; c = (t-w*w)/(s+w); r = p/q; p = 2.0*s*r-(pio2_lo-2.0*c); q = pio4_hi-2.0*w; t = pio4_hi-(p-q); } if(expsign>0) return t; else return -t; } diff --git a/lib/msun/src/e_atan2.c b/lib/msun/src/e_atan2.c index f4d3ed2e00db..45c00199458b 100644 --- a/lib/msun/src/e_atan2.c +++ b/lib/msun/src/e_atan2.c @@ -1,127 +1,126 @@ /* @(#)e_atan2.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* atan2(y,x) * Method : * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). * 2. Reduce x to positive by (if x and y are unexceptional): * ARG (x+iy) = arctan(y/x) ... if x > 0, * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, * * Special cases: * * ATAN2((anything), NaN ) is NaN; * ATAN2(NAN , (anything) ) is NaN; * ATAN2(+-0, +(anything but NaN)) is +-0 ; * ATAN2(+-0, -(anything but NaN)) is +-pi ; * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; * ATAN2(+-INF,+INF ) is +-pi/4 ; * ATAN2(+-INF,-INF ) is +-3pi/4; * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static volatile double tiny = 1.0e-300; static const double zero = 0.0, pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ pi = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */ static volatile double pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ double atan2(double y, double x) { double z; int32_t k,m,hx,hy,ix,iy; u_int32_t lx,ly; EXTRACT_WORDS(hx,lx,x); ix = hx&0x7fffffff; EXTRACT_WORDS(hy,ly,y); iy = hy&0x7fffffff; if(((ix|((lx|-lx)>>31))>0x7ff00000)|| ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ return nan_mix(x, y); if(hx==0x3ff00000&&lx==0) return atan(y); /* x=1.0 */ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ /* when y = 0 */ if((iy|ly)==0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi+tiny;/* atan(+0,-anything) = pi */ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* when x is INF */ if(ix==0x7ff00000) { if(iy==0x7ff00000) { switch(m) { case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ } } else { switch(m) { case 0: return zero ; /* atan(+...,+INF) */ case 1: return -zero ; /* atan(-...,+INF) */ case 2: return pi+tiny ; /* atan(+...,-INF) */ case 3: return -pi-tiny ; /* atan(-...,-INF) */ } } } /* when y is INF */ if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* compute y/x */ k = (iy-ix)>>20; if(k > 60) { /* |y/x| > 2**60 */ z=pi_o_2+0.5*pi_lo; m&=1; } else if(hx<0&&k<-60) z=0.0; /* 0 > |y|/x > -2**-60 */ else z=atan(fabs(y/x)); /* safe to do y/x */ switch (m) { case 0: return z ; /* atan(+,+) */ case 1: return -z ; /* atan(-,+) */ case 2: return pi-(z-pi_lo);/* atan(+,-) */ default: /* case 3 */ return (z-pi_lo)-pi;/* atan(-,-) */ } } #if LDBL_MANT_DIG == 53 __weak_reference(atan2, atan2l); #endif diff --git a/lib/msun/src/e_atan2f.c b/lib/msun/src/e_atan2f.c index af8c00851476..408f3646f612 100644 --- a/lib/msun/src/e_atan2f.c +++ b/lib/msun/src/e_atan2f.c @@ -1,94 +1,93 @@ /* e_atan2f.c -- float version of e_atan2.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static volatile float tiny = 1.0e-30; static const float zero = 0.0, pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */ pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */ pi = 3.1415927410e+00; /* 0x40490fdb */ static volatile float pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */ float atan2f(float y, float x) { float z; int32_t k,m,hx,hy,ix,iy; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; GET_FLOAT_WORD(hy,y); iy = hy&0x7fffffff; if((ix>0x7f800000)|| (iy>0x7f800000)) /* x or y is NaN */ return nan_mix(x, y); if(hx==0x3f800000) return atanf(y); /* x=1.0 */ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ /* when y = 0 */ if(iy==0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi+tiny;/* atan(+0,-anything) = pi */ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* when x is INF */ if(ix==0x7f800000) { if(iy==0x7f800000) { switch(m) { case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ } } else { switch(m) { case 0: return zero ; /* atan(+...,+INF) */ case 1: return -zero ; /* atan(-...,+INF) */ case 2: return pi+tiny ; /* atan(+...,-INF) */ case 3: return -pi-tiny ; /* atan(-...,-INF) */ } } } /* when y is INF */ if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* compute y/x */ k = (iy-ix)>>23; if(k > 26) { /* |y/x| > 2**26 */ z=pi_o_2+(float)0.5*pi_lo; m&=1; } else if(k<-26&&hx<0) z=0.0; /* 0 > |y|/x > -2**-26 */ else z=atanf(fabsf(y/x)); /* safe to do y/x */ switch (m) { case 0: return z ; /* atan(+,+) */ case 1: return -z ; /* atan(-,+) */ case 2: return pi-(z-pi_lo);/* atan(+,-) */ default: /* case 3 */ return (z-pi_lo)-pi;/* atan(-,-) */ } } diff --git a/lib/msun/src/e_atan2l.c b/lib/msun/src/e_atan2l.c index 722334f76791..66fe42bd8aa8 100644 --- a/lib/msun/src/e_atan2l.c +++ b/lib/msun/src/e_atan2l.c @@ -1,118 +1,117 @@ /* @(#)e_atan2.c 1.3 95/01/18 */ /* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* * See comments in e_atan2.c. * Converted to long double by David Schultz . */ #include #include "invtrig.h" #include "math.h" #include "math_private.h" static volatile long double tiny = 1.0e-300; static const long double zero = 0.0; #ifdef __i386__ /* XXX Work around the fact that gcc truncates long double constants on i386 */ static volatile double pi1 = 3.14159265358979311600e+00, /* 0x1.921fb54442d18p+1 */ pi2 = 1.22514845490862001043e-16; /* 0x1.1a80000000000p-53 */ #define pi ((long double)pi1 + pi2) #else static const long double pi = 3.14159265358979323846264338327950280e+00L; #endif long double atan2l(long double y, long double x) { union IEEEl2bits ux, uy; long double z; int32_t k,m; int16_t exptx, expsignx, expty, expsigny; uy.e = y; expsigny = uy.xbits.expsign; expty = expsigny & 0x7fff; ux.e = x; expsignx = ux.xbits.expsign; exptx = expsignx & 0x7fff; if ((exptx==BIAS+LDBL_MAX_EXP && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) || /* x is NaN */ (expty==BIAS+LDBL_MAX_EXP && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* y is NaN */ return nan_mix(x, y); if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) return atanl(y); /* x=1.0 */ m = ((expsigny>>15)&1)|((expsignx>>14)&2); /* 2*sign(x)+sign(y) */ /* when y = 0 */ if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi+tiny;/* atan(+0,-anything) = pi */ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; /* when x is INF */ if(exptx==BIAS+LDBL_MAX_EXP) { if(expty==BIAS+LDBL_MAX_EXP) { switch(m) { case 0: return pio2_hi*0.5+tiny;/* atan(+INF,+INF) */ case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */ case 2: return 1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/ case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/ } } else { switch(m) { case 0: return zero ; /* atan(+...,+INF) */ case 1: return -zero ; /* atan(-...,+INF) */ case 2: return pi+tiny ; /* atan(+...,-INF) */ case 3: return -pi-tiny ; /* atan(-...,-INF) */ } } } /* when y is INF */ if(expty==BIAS+LDBL_MAX_EXP) return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; /* compute y/x */ k = expty-exptx; if(k > LDBL_MANT_DIG+2) { /* |y/x| huge */ z=pio2_hi+pio2_lo; m&=1; } else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0; /* |y/x| tiny, x<0 */ else z=atanl(fabsl(y/x)); /* safe to do y/x */ switch (m) { case 0: return z ; /* atan(+,+) */ case 1: return -z ; /* atan(-,+) */ case 2: return pi-(z-pi_lo);/* atan(+,-) */ default: /* case 3 */ return (z-pi_lo)-pi;/* atan(-,-) */ } } diff --git a/lib/msun/src/e_atanh.c b/lib/msun/src/e_atanh.c index 3eabaaf82403..4e13c3fc1661 100644 --- a/lib/msun/src/e_atanh.c +++ b/lib/msun/src/e_atanh.c @@ -1,66 +1,65 @@ /* @(#)e_atanh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* atanh(x) * Method : * 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 * * For x<0.5 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) * * 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. * */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, huge = 1e300; static const double zero = 0.0; double atanh(double x) { double t; int32_t hx,ix; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); ix = hx&0x7fffffff; if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */ return (x-x)/(x-x); if(ix==0x3ff00000) return x/zero; if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */ SET_HIGH_WORD(x,ix); if(ix<0x3fe00000) { /* x < 0.5 */ t = x+x; t = 0.5*log1p(t+t*x/(one-x)); } else t = 0.5*log1p((x+x)/(one-x)); if(hx>=0) return t; else return -t; } #if LDBL_MANT_DIG == 53 __weak_reference(atanh, atanhl); #endif diff --git a/lib/msun/src/e_atanhf.c b/lib/msun/src/e_atanhf.c index 134513e5b817..a2d6b69a6812 100644 --- a/lib/msun/src/e_atanhf.c +++ b/lib/msun/src/e_atanhf.c @@ -1,43 +1,42 @@ /* e_atanhf.c -- float version of e_atanh.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0, huge = 1e30; static const float zero = 0.0; float atanhf(float x) { float t; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if (ix>0x3f800000) /* |x|>1 */ return (x-x)/(x-x); if(ix==0x3f800000) return x/zero; if(ix<0x31800000&&(huge+x)>zero) return x; /* x<2**-28 */ SET_FLOAT_WORD(x,ix); if(ix<0x3f000000) { /* x < 0.5 */ t = x+x; t = (float)0.5*log1pf(t+t*x/(one-x)); } else t = (float)0.5*log1pf((x+x)/(one-x)); if(hx>=0) return t; else return -t; } diff --git a/lib/msun/src/e_atanhl.c b/lib/msun/src/e_atanhl.c index 66a301f52ab6..331328e1ae1f 100644 --- a/lib/msun/src/e_atanhl.c +++ b/lib/msun/src/e_atanhl.c @@ -1,72 +1,71 @@ /* from: FreeBSD: head/lib/msun/src/e_atanh.c 176451 2008-02-22 02:30:36Z das */ /* @(#)e_atanh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* * See e_atanh.c for complete comments. * * Converted to long double by David Schultz and * Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" /* EXP_TINY is the threshold below which we use atanh(x) ~= x. */ #if LDBL_MANT_DIG == 64 #define EXP_TINY -34 #elif LDBL_MANT_DIG == 113 #define EXP_TINY -58 #else #error "Unsupported long double format" #endif #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const double one = 1.0, huge = 1e300; static const double zero = 0.0; long double atanhl(long double x) { long double t; uint16_t hx, ix; ENTERI(); GET_LDBL_EXPSIGN(hx, x); ix = hx & 0x7fff; if (ix >= 0x3fff) /* |x| >= 1, or NaN or misnormal */ RETURNI(fabsl(x) == 1 ? x / zero : (x - x) / (x - x)); if (ix < BIAS + EXP_TINY && (huge + x) > zero) RETURNI(x); /* x is tiny */ SET_LDBL_EXPSIGN(x, ix); if (ix < 0x3ffe) { /* |x| < 0.5, or misnormal */ t = x+x; t = 0.5*log1pl(t+t*x/(one-x)); } else t = 0.5*log1pl((x+x)/(one-x)); RETURNI((hx & 0x8000) == 0 ? t : -t); } diff --git a/lib/msun/src/e_cosh.c b/lib/msun/src/e_cosh.c index 56ec7d56093d..60b9aa2c7dd2 100644 --- a/lib/msun/src/e_cosh.c +++ b/lib/msun/src/e_cosh.c @@ -1,83 +1,82 @@ /* @(#)e_cosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* cosh(x) * Method : * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 * 1. Replace x by |x| (cosh(x) = cosh(-x)). * 2. * [ exp(x) - 1 ]^2 * 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- * 2*exp(x) * * exp(x) + 1/exp(x) * ln2/2 <= x <= 22 : cosh(x) := ------------------- * 2 * 22 <= x <= lnovft : cosh(x) := exp(x)/2 * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) * ln2ovft < x : cosh(x) := huge*huge (overflow) * * Special cases: * cosh(x) is |x| if x is +INF, -INF, or NaN. * only cosh(0)=1 is exact for finite x. */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, half=0.5, huge = 1.0e300; double cosh(double x) { double t,w; int32_t ix; /* High word of |x|. */ GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3fd62e43) { t = expm1(fabs(x)); w = one+t; if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ return one+(t*t)/(w+w); } /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ if (ix < 0x40360000) { t = exp(fabs(x)); return half*t+half/t; } /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ if (ix < 0x40862E42) return half*exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ if (ix<=0x408633CE) return __ldexp_exp(fabs(x), -1); /* |x| > overflowthresold, cosh(x) overflow */ return huge*huge; } #if (LDBL_MANT_DIG == 53) __weak_reference(cosh, coshl); #endif diff --git a/lib/msun/src/e_coshf.c b/lib/msun/src/e_coshf.c index 8c5457e24a51..40443b8b84d3 100644 --- a/lib/msun/src/e_coshf.c +++ b/lib/msun/src/e_coshf.c @@ -1,57 +1,56 @@ /* e_coshf.c -- float version of e_cosh.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0, half=0.5, huge = 1.0e30; float coshf(float x) { float t,w; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* x is INF or NaN */ if(ix>=0x7f800000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3eb17218) { t = expm1f(fabsf(x)); w = one+t; if (ix<0x39800000) return one; /* cosh(tiny) = 1 */ return one+(t*t)/(w+w); } /* |x| in [0.5*ln2,9], return (exp(|x|)+1/exp(|x|))/2; */ if (ix < 0x41100000) { t = expf(fabsf(x)); return half*t+half/t; } /* |x| in [9, log(maxfloat)] return half*exp(|x|) */ if (ix < 0x42b17217) return half*expf(fabsf(x)); /* |x| in [log(maxfloat), overflowthresold] */ if (ix<=0x42b2d4fc) return __ldexp_expf(fabsf(x), -1); /* |x| > overflowthresold, cosh(x) overflow */ return huge*huge; } diff --git a/lib/msun/src/e_coshl.c b/lib/msun/src/e_coshl.c index de54b8183bbb..efb5094d39f9 100644 --- a/lib/msun/src/e_coshl.c +++ b/lib/msun/src/e_coshl.c @@ -1,130 +1,129 @@ /* from: FreeBSD: head/lib/msun/src/e_coshl.c XXX */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_cosh.c for complete comments. * * Converted to long double by Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #include "k_expl.h" #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L; #if LDBL_MANT_DIG == 64 /* * Domain [-1, 1], range ~[-1.8211e-21, 1.8211e-21]: * |cosh(x) - c(x)| < 2**-68.8 */ static const union IEEEl2bits C4u = LD80C(0xaaaaaaaaaaaaac78, -5, 4.16666666666666682297e-2L); #define C4 C4u.e static const double C2 = 0.5, C6 = 1.3888888888888616e-3, /* 0x16c16c16c16b99.0p-62 */ C8 = 2.4801587301767953e-5, /* 0x1a01a01a027061.0p-68 */ C10 = 2.7557319163300398e-7, /* 0x127e4fb6c9b55f.0p-74 */ C12 = 2.0876768371393075e-9, /* 0x11eed99406a3f4.0p-81 */ C14 = 1.1469537039374480e-11, /* 0x1938c67cd18c48.0p-89 */ C16 = 4.8473490896852041e-14; /* 0x1b49c429701e45.0p-97 */ #elif LDBL_MANT_DIG == 113 /* * Domain [-1, 1], range ~[-2.3194e-37, 2.3194e-37]: * |cosh(x) - c(x)| < 2**-121.69 */ static const long double C4 = 4.16666666666666666666666666666666225e-2L, /* 0x1555555555555555555555555554e.0p-117L */ C6 = 1.38888888888888888888888888889434831e-3L, /* 0x16c16c16c16c16c16c16c16c1dd7a.0p-122L */ C8 = 2.48015873015873015873015871870962089e-5L, /* 0x1a01a01a01a01a01a01a017af2756.0p-128L */ C10 = 2.75573192239858906525574318600800201e-7L, /* 0x127e4fb7789f5c72ef01c8a040640.0p-134L */ C12 = 2.08767569878680989791444691755468269e-9L, /* 0x11eed8eff8d897b543d0679607399.0p-141L */ C14= 1.14707455977297247387801189650495351e-11L, /* 0x193974a8c07c9d24ae169a7fa9b54.0p-149L */ C16 = 4.77947733238737883626416876486279985e-14L; /* 0x1ae7f3e733b814d4e1b90f5727fe4.0p-157L */ static const double C2 = 0.5, C18 = 1.5619206968597871e-16, /* 0x16827863b9900b.0p-105 */ C20 = 4.1103176218528049e-19, /* 0x1e542ba3d3c269.0p-114 */ C22 = 8.8967926401641701e-22, /* 0x10ce399542a014.0p-122 */ C24 = 1.6116681626523904e-24, /* 0x1f2c981d1f0cb7.0p-132 */ C26 = 2.5022374732804632e-27; /* 0x18c7ecf8b2c4a0.0p-141 */ #else #error "Unsupported long double format" #endif /* LDBL_MANT_DIG == 64 */ /* log(2**16385 - 0.5) rounded up: */ static const float o_threshold = 1.13572168e4; /* 0xb174de.0p-10 */ long double coshl(long double x) { long double hi,lo,x2,x4; #if LDBL_MANT_DIG == 113 double dx2; #endif uint16_t ix; GET_LDBL_EXPSIGN(ix,x); ix &= 0x7fff; /* x is INF or NaN */ if(ix>=0x7fff) return x*x; ENTERI(); /* |x| < 1, return 1 or c(x) */ if(ix<0x3fff) { if (ix o_threshold, cosh(x) overflow */ RETURNI(huge*huge); } diff --git a/lib/msun/src/e_exp.c b/lib/msun/src/e_exp.c index afbcdb3db7b6..040a28260db0 100644 --- a/lib/msun/src/e_exp.c +++ b/lib/msun/src/e_exp.c @@ -1,162 +1,161 @@ /* @(#)e_exp.c 1.6 04/04/22 */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* exp(x) * Returns the exponential of x. * * Method * 1. Argument reduction: * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2. * * Here r will be represented as r = hi-lo for better * accuracy. * * 2. Approximation of exp(r) by a special rational function on * the interval [0,0.34658]: * Write * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... * We use a special Remes algorithm on [0,0.34658] to generate * a polynomial of degree 5 to approximate R. The maximum error * of this polynomial approximation is bounded by 2**-59. In * other words, * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 * (where z=r*r, and the values of P1 to P5 are listed below) * and * | 5 | -59 * | 2.0+P1*z+...+P5*z - R(z) | <= 2 * | | * The computation of exp(r) thus becomes * 2*r * exp(r) = 1 + ------- * R - r * r*R1(r) * = 1 + r + ----------- (for better accuracy) * 2 - R1(r) * where * 2 4 10 * R1(r) = r - (P1*r + P2*r + ... + P5*r ). * * 3. Scale back to obtain exp(x): * From step 1, we have * exp(x) = 2^k * exp(r) * * Special cases: * exp(INF) is INF, exp(NaN) is NaN; * exp(-INF) is 0, and * for finite argument, only exp(0)=1 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 7.09782712893383973096e+02 then exp(x) overflow * if x < -7.45133219101941108420e+02 then exp(x) underflow * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, halF[2] = {0.5,-0.5,}, o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ static volatile double huge = 1.0e+300, twom1000= 9.33263618503218878990e-302; /* 2**-1000=0x01700000,0*/ double exp(double x) /* default IEEE double exp */ { double y,hi=0.0,lo=0.0,c,t,twopk; int32_t k=0,xsb; u_int32_t hx; GET_HIGH_WORD(hx,x); xsb = (hx>>31)&1; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out non-finite argument */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { u_int32_t lx; GET_LOW_WORD(lx,x); if(((hx&0xfffff)|lx)!=0) return x+x; /* NaN */ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ } if(x > o_threshold) return huge*huge; /* overflow */ if(x < u_threshold) return twom1000*twom1000; /* underflow */ } /* argument reduction */ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; } else { k = (int)(invln2*x+halF[xsb]); t = k; hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ lo = t*ln2LO[0]; } STRICT_ASSIGN(double, x, hi - lo); } else if(hx < 0x3e300000) { /* when |x|<2**-28 */ if(huge+x>one) return one+x;/* trigger inexact */ } else k = 0; /* x is now in primary range */ t = x*x; if(k >= -1021) INSERT_WORDS(twopk,((u_int32_t)(0x3ff+k))<<20, 0); else INSERT_WORDS(twopk,((u_int32_t)(0x3ff+(k+1000)))<<20, 0); c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); if(k==0) return one-((x*c)/(c-2.0)-x); else y = one-((lo-(x*c)/(2.0-c))-hi); if(k >= -1021) { if (k==1024) return y*2.0*0x1p1023; return y*twopk; } else { return y*twopk*twom1000; } } #if (LDBL_MANT_DIG == 53) __weak_reference(exp, expl); #endif diff --git a/lib/msun/src/e_expf.c b/lib/msun/src/e_expf.c index 2dbce9dd870d..fe2e6779469f 100644 --- a/lib/msun/src/e_expf.c +++ b/lib/msun/src/e_expf.c @@ -1,96 +1,95 @@ /* e_expf.c -- float version of e_exp.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" static const float one = 1.0, halF[2] = {0.5,-0.5,}, o_threshold= 8.8721679688e+01, /* 0x42b17180 */ u_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */ ln2HI[2] ={ 6.9314575195e-01, /* 0x3f317200 */ -6.9314575195e-01,}, /* 0xbf317200 */ ln2LO[2] ={ 1.4286067653e-06, /* 0x35bfbe8e */ -1.4286067653e-06,}, /* 0xb5bfbe8e */ invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ /* * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 */ P1 = 1.6666625440e-1, /* 0xaaaa8f.0p-26 */ P2 = -2.7667332906e-3; /* -0xb55215.0p-32 */ static volatile float huge = 1.0e+30, twom100 = 7.8886090522e-31; /* 2**-100=0x0d800000 */ float expf(float x) { float y,hi=0.0,lo=0.0,c,t,twopk; int32_t k=0,xsb; u_int32_t hx; GET_FLOAT_WORD(hx,x); xsb = (hx>>31)&1; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out non-finite argument */ if(hx >= 0x42b17218) { /* if |x|>=88.721... */ if(hx>0x7f800000) return x+x; /* NaN */ if(hx==0x7f800000) return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ if(x > o_threshold) return huge*huge; /* overflow */ if(x < u_threshold) return twom100*twom100; /* underflow */ } /* argument reduction */ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; } else { k = invln2*x+halF[xsb]; t = k; hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ lo = t*ln2LO[0]; } STRICT_ASSIGN(float, x, hi - lo); } else if(hx < 0x39000000) { /* when |x|<2**-14 */ if(huge+x>one) return one+x;/* trigger inexact */ } else k = 0; /* x is now in primary range */ t = x*x; if(k >= -125) SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+k))<<23); else SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+(k+100)))<<23); c = x - t*(P1+t*P2); if(k==0) return one-((x*c)/(c-(float)2.0)-x); else y = one-((lo-(x*c)/((float)2.0-c))-hi); if(k >= -125) { if(k==128) return y*2.0F*0x1p127F; return y*twopk; } else { return y*twopk*twom100; } } diff --git a/lib/msun/src/e_fmod.c b/lib/msun/src/e_fmod.c index fdfb56c2a475..dd96f6bcd7cb 100644 --- a/lib/msun/src/e_fmod.c +++ b/lib/msun/src/e_fmod.c @@ -1,136 +1,135 @@ /* @(#)e_fmod.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * fmod(x,y) * Return x mod y in exact arithmetic * Method: shift and subtract */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, Zero[] = {0.0, -0.0,}; double fmod(double x, double y) { int32_t n,hx,hy,hz,ix,iy,sx,i; u_int32_t lx,ly,lz; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hy,ly,y); sx = hx&0x80000000; /* sign of x */ hx ^=sx; /* |x| */ hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(hx<=hy) { if((hx>31]; /* |x|=|y| return x*0*/ } /* determine ix = ilogb(x) */ if(hx<0x00100000) { /* subnormal x */ if(hx==0) { for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; } else { for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; } } else ix = (hx>>20)-1023; /* determine iy = ilogb(y) */ if(hy<0x00100000) { /* subnormal y */ if(hy==0) { for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; } else { for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; } } else iy = (hy>>20)-1023; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -1022) hx = 0x00100000|(0x000fffff&hx); else { /* subnormal x, shift x to normal */ n = -1022-ix; if(n<=31) { hx = (hx<>(32-n)); lx <<= n; } else { hx = lx<<(n-32); lx = 0; } } if(iy >= -1022) hy = 0x00100000|(0x000fffff&hy); else { /* subnormal y, shift y to normal */ n = -1022-iy; if(n<=31) { hy = (hy<>(32-n)); ly <<= n; } else { hy = ly<<(n-32); ly = 0; } } /* fix point fmod */ n = ix - iy; while(n--) { hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} else { if((hz|lz)==0) /* return sign(x)*0 */ return Zero[(u_int32_t)sx>>31]; hx = hz+hz+(lz>>31); lx = lz+lz; } } hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} /* convert back to floating value and restore the sign */ if((hx|lx)==0) /* return sign(x)*0 */ return Zero[(u_int32_t)sx>>31]; while(hx<0x00100000) { /* normalize x */ hx = hx+hx+(lx>>31); lx = lx+lx; iy -= 1; } if(iy>= -1022) { /* normalize output */ hx = ((hx-0x00100000)|((iy+1023)<<20)); INSERT_WORDS(x,hx|sx,lx); } else { /* subnormal output */ n = -1022 - iy; if(n<=20) { lx = (lx>>n)|((u_int32_t)hx<<(32-n)); hx >>= n; } else if (n<=31) { lx = (hx<<(32-n))|(lx>>n); hx = sx; } else { lx = hx>>(n-32); hx = sx; } INSERT_WORDS(x,hx|sx,lx); x *= one; /* create necessary signal */ } return x; /* exact output */ } #if (LDBL_MANT_DIG == 53) __weak_reference(fmod, fmodl); #endif diff --git a/lib/msun/src/e_fmodf.c b/lib/msun/src/e_fmodf.c index 0e6633fbe739..a7d1a0c22acd 100644 --- a/lib/msun/src/e_fmodf.c +++ b/lib/msun/src/e_fmodf.c @@ -1,102 +1,101 @@ /* e_fmodf.c -- float version of e_fmod.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * fmodf(x,y) * Return x mod y in exact arithmetic * Method: shift and subtract */ #include "math.h" #include "math_private.h" static const float one = 1.0, Zero[] = {0.0, -0.0,}; float fmodf(float x, float y) { int32_t n,hx,hy,hz,ix,iy,sx,i; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); sx = hx&0x80000000; /* sign of x */ hx ^=sx; /* |x| */ hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if(hy==0||(hx>=0x7f800000)|| /* y=0,or x not finite */ (hy>0x7f800000)) /* or y is NaN */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(hx>31]; /* |x|=|y| return x*0*/ /* determine ix = ilogb(x) */ if(hx<0x00800000) { /* subnormal x */ for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; } else ix = (hx>>23)-127; /* determine iy = ilogb(y) */ if(hy<0x00800000) { /* subnormal y */ for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1; } else iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) hx = 0x00800000|(0x007fffff&hx); else { /* subnormal x, shift x to normal */ n = -126-ix; hx = hx<= -126) hy = 0x00800000|(0x007fffff&hy); else { /* subnormal y, shift y to normal */ n = -126-iy; hy = hy<>31]; hx = hz+hz; } } hz=hx-hy; if(hz>=0) {hx=hz;} /* convert back to floating value and restore the sign */ if(hx==0) /* return sign(x)*0 */ return Zero[(u_int32_t)sx>>31]; while(hx<0x00800000) { /* normalize x */ hx = hx+hx; iy -= 1; } if(iy>= -126) { /* normalize output */ hx = ((hx-0x00800000)|((iy+127)<<23)); SET_FLOAT_WORD(x,hx|sx); } else { /* subnormal output */ n = -126 - iy; hx >>= n; SET_FLOAT_WORD(x,hx|sx); x *= one; /* create necessary signal */ } return x; /* exact output */ } diff --git a/lib/msun/src/e_fmodl.c b/lib/msun/src/e_fmodl.c index 8a348ee117e7..6984b52fc8d5 100644 --- a/lib/msun/src/e_fmodl.c +++ b/lib/msun/src/e_fmodl.c @@ -1,147 +1,146 @@ /* @(#)e_fmod.c 1.3 95/01/18 */ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define BIAS (LDBL_MAX_EXP - 1) #if LDBL_MANL_SIZE > 32 typedef uint64_t manl_t; #else typedef uint32_t manl_t; #endif #if LDBL_MANH_SIZE > 32 typedef uint64_t manh_t; #else typedef uint32_t manh_t; #endif /* * These macros add and remove an explicit integer bit in front of the * fractional mantissa, if the architecture doesn't have such a bit by * default already. */ #ifdef LDBL_IMPLICIT_NBIT #define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE)) #define HFRAC_BITS LDBL_MANH_SIZE #else #define SET_NBIT(hx) (hx) #define HFRAC_BITS (LDBL_MANH_SIZE - 1) #endif #define MANL_SHIFT (LDBL_MANL_SIZE - 1) static const long double one = 1.0, Zero[] = {0.0, -0.0,}; /* * fmodl(x,y) * Return x mod y in exact arithmetic * Method: shift and subtract * * Assumptions: * - The low part of the mantissa fits in a manl_t exactly. * - The high part of the mantissa fits in an int64_t with enough room * for an explicit integer bit in front of the fractional bits. */ long double fmodl(long double x, long double y) { union IEEEl2bits ux, uy; int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */ manh_t hy; manl_t lx,ly,lz; int ix,iy,n,sx; ux.e = x; uy.e = y; sx = ux.bits.sign; /* purge off exception values */ if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */ (ux.bits.exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */ (uy.bits.exp == BIAS + LDBL_MAX_EXP && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(ux.bits.exp<=uy.bits.exp) { if((ux.bits.exp>MANL_SHIFT); lx = lx+lx;} else { if ((hz|lz)==0) /* return sign(x)*0 */ return Zero[sx]; hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; } } hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} /* convert back to floating value and restore the sign */ if((hx|lx)==0) /* return sign(x)*0 */ return Zero[sx]; while(hx<(1ULL<>MANL_SHIFT); lx = lx+lx; iy -= 1; } ux.bits.manh = hx; /* The mantissa is truncated here if needed. */ ux.bits.manl = lx; if (iy < LDBL_MIN_EXP) { ux.bits.exp = iy + (BIAS + 512); ux.e *= 0x1p-512; } else { ux.bits.exp = iy + BIAS; } x = ux.e * one; /* create necessary signal */ return x; /* exact output */ } diff --git a/lib/msun/src/e_gamma.c b/lib/msun/src/e_gamma.c index 7757337b59af..0b1db544c35e 100644 --- a/lib/msun/src/e_gamma.c +++ b/lib/msun/src/e_gamma.c @@ -1,31 +1,30 @@ /* @(#)e_gamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* gamma(x) * Return the logarithm of the Gamma function of x. * * Method: call gamma_r */ #include "math.h" #include "math_private.h" extern int signgam; double gamma(double x) { return gamma_r(x,&signgam); } diff --git a/lib/msun/src/e_gamma_r.c b/lib/msun/src/e_gamma_r.c index f204685c3f7a..3f62026d90c1 100644 --- a/lib/msun/src/e_gamma_r.c +++ b/lib/msun/src/e_gamma_r.c @@ -1,30 +1,29 @@ /* @(#)e_gamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* gamma_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function * with user provide pointer for the sign of Gamma(x). * * Method: See lgamma_r */ #include "math.h" #include "math_private.h" double gamma_r(double x, int *signgamp) { return lgamma_r(x,signgamp); } diff --git a/lib/msun/src/e_gammaf.c b/lib/msun/src/e_gammaf.c index 3afef79de53a..98da5711e811 100644 --- a/lib/msun/src/e_gammaf.c +++ b/lib/msun/src/e_gammaf.c @@ -1,32 +1,31 @@ /* e_gammaf.c -- float version of e_gamma.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* gammaf(x) * Return the logarithm of the Gamma function of x. * * Method: call gammaf_r */ #include "math.h" #include "math_private.h" extern int signgam; float gammaf(float x) { return gammaf_r(x,&signgam); } diff --git a/lib/msun/src/e_gammaf_r.c b/lib/msun/src/e_gammaf_r.c index 5b3bd535aa42..ae80c1bae2cc 100644 --- a/lib/msun/src/e_gammaf_r.c +++ b/lib/msun/src/e_gammaf_r.c @@ -1,31 +1,30 @@ /* e_gammaf_r.c -- float version of e_gamma_r.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* gammaf_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function * with user provide pointer for the sign of Gamma(x). * * Method: See lgammaf_r */ #include "math.h" #include "math_private.h" float gammaf_r(float x, int *signgamp) { return lgammaf_r(x,signgamp); } diff --git a/lib/msun/src/e_hypot.c b/lib/msun/src/e_hypot.c index 8d9c2b11dd97..13986a20da3b 100644 --- a/lib/msun/src/e_hypot.c +++ b/lib/msun/src/e_hypot.c @@ -1,127 +1,126 @@ /* @(#)e_hypot.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* hypot(x,y) * * Method : * If (assume round-to-nearest) z=x*x+y*y * has error less than sqrt(2)/2 ulp, than * sqrt(z) has error less than 1 ulp (exercise). * * So, compute sqrt(x*x+y*y) with some care as * follows to get the error below 1 ulp: * * Assume x>y>0; * (if possible, set rounding to round-to-nearest) * 1. if x > 2y use * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y * where x1 = x with lower 32 bits cleared, x2 = x-x1; else * 2. if x <= 2y use * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, * y1= y with lower 32 bits chopped, y2 = y-y1. * * NOTE: scaling may be necessary if some argument is too * large or too tiny * * Special cases: * hypot(x,y) is INF if x or y is +INF or -INF; else * hypot(x,y) is NAN if x or y is NAN. * * Accuracy: * hypot(x,y) returns sqrt(x^2+y^2) with error less * than 1 ulps (units in the last place) */ #include #include "math.h" #include "math_private.h" double hypot(double x, double y) { double a,b,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_HIGH_WORD(ha,x); ha &= 0x7fffffff; GET_HIGH_WORD(hb,y); hb &= 0x7fffffff; if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} a = fabs(a); b = fabs(b); if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ k=0; if(ha > 0x5f300000) { /* a>2**500 */ if(ha >= 0x7ff00000) { /* Inf or NaN */ u_int32_t low; /* Use original arg order iff result is NaN; quieten sNaNs. */ w = fabsl(x+0.0L)-fabs(y+0); GET_LOW_WORD(low,a); if(((ha&0xfffff)|low)==0) w = a; GET_LOW_WORD(low,b); if(((hb^0x7ff00000)|low)==0) w = b; return w; } /* scale a and b by 2**-600 */ ha -= 0x25800000; hb -= 0x25800000; k += 600; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } if(hb < 0x20b00000) { /* b < 2**-500 */ if(hb <= 0x000fffff) { /* subnormal b or 0 */ u_int32_t low; GET_LOW_WORD(low,b); if((hb|low)==0) return a; t1=0; SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */ b *= t1; a *= t1; k -= 1022; } else { /* scale a and b by 2^600 */ ha += 0x25800000; /* a *= 2^600 */ hb += 0x25800000; /* b *= 2^600 */ k -= 600; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } } /* medium size a and b */ w = a-b; if (w>b) { t1 = 0; SET_HIGH_WORD(t1,ha); t2 = a-t1; w = sqrt(t1*t1-(b*(-b)-t2*(a+t1))); } else { a = a+a; y1 = 0; SET_HIGH_WORD(y1,hb); y2 = b - y1; t1 = 0; SET_HIGH_WORD(t1,ha+0x00100000); t2 = a - t1; w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { t1 = 0.0; SET_HIGH_WORD(t1,(1023+k)<<20); return t1*w; } else return w; } #if LDBL_MANT_DIG == 53 __weak_reference(hypot, hypotl); #endif diff --git a/lib/msun/src/e_hypotf.c b/lib/msun/src/e_hypotf.c index c976fd33014d..e45486ee912f 100644 --- a/lib/msun/src/e_hypotf.c +++ b/lib/msun/src/e_hypotf.c @@ -1,81 +1,80 @@ /* e_hypotf.c -- float version of e_hypot.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" float hypotf(float x, float y) { float a,b,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_FLOAT_WORD(ha,x); ha &= 0x7fffffff; GET_FLOAT_WORD(hb,y); hb &= 0x7fffffff; if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} a = fabsf(a); b = fabsf(b); if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */ k=0; if(ha > 0x58800000) { /* a>2**50 */ if(ha >= 0x7f800000) { /* Inf or NaN */ /* Use original arg order iff result is NaN; quieten sNaNs. */ w = fabsl(x+0.0L)-fabsf(y+0); if(ha == 0x7f800000) w = a; if(hb == 0x7f800000) w = b; return w; } /* scale a and b by 2**-68 */ ha -= 0x22000000; hb -= 0x22000000; k += 68; SET_FLOAT_WORD(a,ha); SET_FLOAT_WORD(b,hb); } if(hb < 0x26800000) { /* b < 2**-50 */ if(hb <= 0x007fffff) { /* subnormal b or 0 */ if(hb==0) return a; SET_FLOAT_WORD(t1,0x7e800000); /* t1=2^126 */ b *= t1; a *= t1; k -= 126; } else { /* scale a and b by 2^68 */ ha += 0x22000000; /* a *= 2^68 */ hb += 0x22000000; /* b *= 2^68 */ k -= 68; SET_FLOAT_WORD(a,ha); SET_FLOAT_WORD(b,hb); } } /* medium size a and b */ w = a-b; if (w>b) { SET_FLOAT_WORD(t1,ha&0xfffff000); t2 = a-t1; w = sqrtf(t1*t1-(b*(-b)-t2*(a+t1))); } else { a = a+a; SET_FLOAT_WORD(y1,hb&0xfffff000); y2 = b - y1; SET_FLOAT_WORD(t1,(ha+0x00800000)&0xfffff000); t2 = a - t1; w = sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { SET_FLOAT_WORD(t1,(127+k)<<23); return t1*w; } else return w; } diff --git a/lib/msun/src/e_hypotl.c b/lib/msun/src/e_hypotl.c index 0a89e3a0e218..a61d7ec241f9 100644 --- a/lib/msun/src/e_hypotl.c +++ b/lib/msun/src/e_hypotl.c @@ -1,122 +1,121 @@ /* From: @(#)e_hypot.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* long double version of hypot(). See e_hypot.c for most comments. */ #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define GET_LDBL_MAN(h, l, v) do { \ union IEEEl2bits uv; \ \ uv.e = v; \ h = uv.bits.manh; \ l = uv.bits.manl; \ } while (0) #undef GET_HIGH_WORD #define GET_HIGH_WORD(i, v) GET_LDBL_EXPSIGN(i, v) #undef SET_HIGH_WORD #define SET_HIGH_WORD(v, i) SET_LDBL_EXPSIGN(v, i) #define DESW(exp) (exp) /* delta expsign word */ #define ESW(exp) (MAX_EXP - 1 + (exp)) /* expsign word */ #define MANT_DIG LDBL_MANT_DIG #define MAX_EXP LDBL_MAX_EXP #if LDBL_MANL_SIZE > 32 typedef uint64_t man_t; #else typedef uint32_t man_t; #endif long double hypotl(long double x, long double y) { long double a=x,b=y,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_HIGH_WORD(ha,x); ha &= 0x7fff; GET_HIGH_WORD(hb,y); hb &= 0x7fff; if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} a = fabsl(a); b = fabsl(b); if((ha-hb)>DESW(MANT_DIG+7)) {return a+b;} /* x/y > 2**(MANT_DIG+7) */ k=0; if(ha > ESW(MAX_EXP/2-12)) { /* a>2**(MAX_EXP/2-12) */ if(ha >= ESW(MAX_EXP)) { /* Inf or NaN */ man_t manh, manl; /* Use original arg order iff result is NaN; quieten sNaNs. */ w = fabsl(x+0.0L)-fabsl(y+0); GET_LDBL_MAN(manh,manl,a); if (manh == LDBL_NBIT && manl == 0) w = a; GET_LDBL_MAN(manh,manl,b); if (hb >= ESW(MAX_EXP) && manh == LDBL_NBIT && manl == 0) w = b; return w; } /* scale a and b by 2**-(MAX_EXP/2+88) */ ha -= DESW(MAX_EXP/2+88); hb -= DESW(MAX_EXP/2+88); k += MAX_EXP/2+88; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } if(hb < ESW(-(MAX_EXP/2-12))) { /* b < 2**-(MAX_EXP/2-12) */ if(hb <= 0) { /* subnormal b or 0 */ man_t manh, manl; GET_LDBL_MAN(manh,manl,b); if((manh|manl)==0) return a; t1=1; SET_HIGH_WORD(t1,ESW(MAX_EXP-2)); /* t1=2^(MAX_EXP-2) */ b *= t1; a *= t1; k -= MAX_EXP-2; } else { /* scale a and b by 2^(MAX_EXP/2+88) */ ha += DESW(MAX_EXP/2+88); hb += DESW(MAX_EXP/2+88); k -= MAX_EXP/2+88; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } } /* medium size a and b */ w = a-b; if (w>b) { t1 = a; union IEEEl2bits uv; uv.e = t1; uv.bits.manl = 0; t1 = uv.e; t2 = a-t1; w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); } else { a = a+a; y1 = b; union IEEEl2bits uv; uv.e = y1; uv.bits.manl = 0; y1 = uv.e; y2 = b - y1; t1 = a; uv.e = t1; uv.bits.manl = 0; t1 = uv.e; t2 = a - t1; w = sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { u_int32_t high; t1 = 1.0; GET_HIGH_WORD(high,t1); SET_HIGH_WORD(t1,high+DESW(k)); return t1*w; } else return w; } diff --git a/lib/msun/src/e_j0.c b/lib/msun/src/e_j0.c index 20e0d36b162e..b6f185b834da 100644 --- a/lib/msun/src/e_j0.c +++ b/lib/msun/src/e_j0.c @@ -1,387 +1,386 @@ /* @(#)e_j0.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* j0(x), y0(x) * Bessel function of the first and second kinds of order zero. * Method -- j0(x): * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... * 2. Reduce x to |x| since j0(x)=j0(-x), and * for x in (0,2) * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) * for x in (2,inf) * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) * as follow: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (cos(x) + sin(x)) * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * (To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one.) * * 3 Special cases * j0(nan)= nan * j0(0) = 1 * j0(inf) = 0 * * Method -- y0(x): * 1. For x<2. * Since * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. * We use the following function to approximate y0, * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 * where * U(z) = u00 + u01*z + ... + u06*z^6 * V(z) = 1 + v01*z + ... + v04*z^4 * with absolute approximation error bounded by 2**-72. * Note: For tiny x, U/V = u0 and j0(x)~1, hence * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) * 2. For x>=2. * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) * by the method mentioned above. * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. */ #include "math.h" #include "math_private.h" static __inline double pzero(double), qzero(double); static const volatile double vone = 1, vzero = 0; static const double huge = 1e300, one = 1.0, invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ /* R0/S0 on [0, 2.00] */ R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ static const double zero = 0, qrtr = 0.25; double j0(double x) { double z, s,c,ss,cc,r,u,v; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return one/(x*x); x = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincos(x, &s, &c); ss = s-c; cc = s+c; if(ix<0x7fe00000) { /* Make sure x+x does not overflow. */ z = -cos(x+x); if ((s*c)0x48000000) z = (invsqrtpi*cc)/sqrt(x); else { u = pzero(x); v = qzero(x); z = invsqrtpi*(u*cc-v*ss)/sqrt(x); } return z; } if(ix<0x3f200000) { /* |x| < 2**-13 */ if(huge+x>one) { /* raise inexact if x != 0 */ if(ix<0x3e400000) return one; /* |x|<2**-27 */ else return one - x*x/4; } } z = x*x; r = z*(R02+z*(R03+z*(R04+z*R05))); s = one+z*(S01+z*(S02+z*(S03+z*S04))); if(ix < 0x3FF00000) { /* |x| < 1.00 */ return one + z*((r/s)-qrtr); } else { u = x/2; return((one+u)*(one-u)+z*(r/s)); } } static const double u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ double y0(double x) { double z, s,c,ss,cc,u,v; int32_t hx,ix,lx; EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; /* * y0(NaN) = NaN. * y0(Inf) = 0. * y0(-Inf) = NaN and raise invalid exception. */ if(ix>=0x7ff00000) return vone/(x+x*x); /* y0(+-0) = -inf and raise divide-by-zero exception. */ if((ix|lx)==0) return -one/vzero; /* y0(x<0) = NaN and raise invalid exception. */ if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) * where x0 = x-pi/4 * Better formula: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) + cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ sincos(x, &s, &c); ss = s-c; cc = s+c; /* * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) */ if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = -cos(x+x); if ((s*c)0x48000000) z = (invsqrtpi*ss)/sqrt(x); else { u = pzero(x); v = qzero(x); z = invsqrtpi*(u*ss+v*cc)/sqrt(x); } return z; } if(ix<=0x3e400000) { /* x < 2**-27 */ return(u00 + tpi*log(x)); } z = x*x; u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); v = one+z*(v01+z*(v02+z*(v03+z*v04))); return(u/v + tpi*(j0(x)*log(x))); } /* The asymptotic expansions of pzero is * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. * For x >= 2, We approximate pzero by * pzero(x) = 1 + (R/S) * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 * S = 1 + pS0*s^2 + ... + pS4*s^10 * and * | pzero(x)-1-R/S | <= 2 ** ( -60.26) */ static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ }; static const double pS8[5] = { 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ }; static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ }; static const double pS5[5] = { 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ }; static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ }; static const double pS3[5] = { 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ }; static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ }; static const double pS2[5] = { 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ }; static __inline double pzero(double x) { const double *p,*q; double z,r,s; int32_t ix; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x40200000) {p = pR8; q= pS8;} else if(ix>=0x40122E8B){p = pR5; q= pS5;} else if(ix>=0x4006DB6D){p = pR3; q= pS3;} else {p = pR2; q= pS2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qzero is * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. * We approximate pzero by * qzero(x) = s*(-1.25 + (R/S)) * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 * S = 1 + qS0*s^2 + ... + qS5*s^12 * and * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) */ static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ }; static const double qS8[6] = { 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ }; static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ }; static const double qS5[6] = { 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ }; static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ }; static const double qS3[6] = { 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ }; static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ }; static const double qS2[6] = { 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ }; static __inline double qzero(double x) { static const double eighth = 0.125; const double *p,*q; double s,r,z; int32_t ix; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x40200000) {p = qR8; q= qS8;} else if(ix>=0x40122E8B){p = qR5; q= qS5;} else if(ix>=0x4006DB6D){p = qR3; q= qS3;} else {p = qR2; q= qS2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return (r/s-eighth)/x; } diff --git a/lib/msun/src/e_j0f.c b/lib/msun/src/e_j0f.c index 1cb318d80851..de04a9fadf6b 100644 --- a/lib/msun/src/e_j0f.c +++ b/lib/msun/src/e_j0f.c @@ -1,341 +1,340 @@ /* e_j0f.c -- float version of e_j0.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_j0.c for complete comments. */ #include "math.h" #include "math_private.h" static __inline float pzerof(float), qzerof(float); static const volatile float vone = 1, vzero = 0; static const float huge = 1e30, one = 1.0, invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */ tpi = 6.3661974669e-01, /* 0x3f22f983 */ /* R0/S0 on [0, 2.00] */ R02 = 1.5625000000e-02, /* 0x3c800000 */ R03 = -1.8997929874e-04, /* 0xb947352e */ R04 = 1.8295404516e-06, /* 0x35f58e88 */ R05 = -4.6183270541e-09, /* 0xb19eaf3c */ S01 = 1.5619102865e-02, /* 0x3c7fe744 */ S02 = 1.1692678527e-04, /* 0x38f53697 */ S03 = 5.1354652442e-07, /* 0x3509daa6 */ S04 = 1.1661400734e-09; /* 0x30a045e8 */ static const float zero = 0, qrtr = 0.25; float j0f(float x) { float z, s,c,ss,cc,r,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) return one/(x*x); x = fabsf(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincosf(x, &s, &c); ss = s-c; cc = s+c; if(ix<0x7f000000) { /* Make sure x+x does not overflow. */ z = -cosf(x+x); if ((s*c)0x58000000) z = (invsqrtpi*cc)/sqrtf(x); /* |x|>2**49 */ else { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*cc-v*ss)/sqrtf(x); } return z; } if(ix<0x3b000000) { /* |x| < 2**-9 */ if(huge+x>one) { /* raise inexact if x != 0 */ if(ix<0x39800000) return one; /* |x|<2**-12 */ else return one - x*x/4; } } z = x*x; r = z*(R02+z*(R03+z*(R04+z*R05))); s = one+z*(S01+z*(S02+z*(S03+z*S04))); if(ix < 0x3F800000) { /* |x| < 1.00 */ return one + z*((r/s)-qrtr); } else { u = x/2; return((one+u)*(one-u)+z*(r/s)); } } static const float u00 = -7.3804296553e-02, /* 0xbd9726b5 */ u01 = 1.7666645348e-01, /* 0x3e34e80d */ u02 = -1.3818567619e-02, /* 0xbc626746 */ u03 = 3.4745343146e-04, /* 0x39b62a69 */ u04 = -3.8140706238e-06, /* 0xb67ff53c */ u05 = 1.9559013964e-08, /* 0x32a802ba */ u06 = -3.9820518410e-11, /* 0xae2f21eb */ v01 = 1.2730483897e-02, /* 0x3c509385 */ v02 = 7.6006865129e-05, /* 0x389f65e0 */ v03 = 2.5915085189e-07, /* 0x348b216c */ v04 = 4.4111031494e-10; /* 0x2ff280c2 */ float y0f(float x) { float z, s,c,ss,cc,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; if(ix>=0x7f800000) return vone/(x+x*x); if(ix==0) return -one/vzero; if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) * where x0 = x-pi/4 * Better formula: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) + cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ sincosf(x, &s, &c); ss = s-c; cc = s+c; /* * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) */ if(ix<0x7f000000) { /* make sure x+x not overflow */ z = -cosf(x+x); if ((s*c)0x58000000) z = (invsqrtpi*ss)/sqrtf(x); /* |x|>2**49 */ else { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*ss+v*cc)/sqrtf(x); } return z; } if(ix<=0x39000000) { /* x < 2**-13 */ return(u00 + tpi*logf(x)); } z = x*x; u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); v = one+z*(v01+z*(v02+z*(v03+z*v04))); return(u/v + tpi*(j0f(x)*logf(x))); } /* The asymptotic expansions of pzero is * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. * For x >= 2, We approximate pzero by * pzero(x) = 1 + (R/S) * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 * S = 1 + pS0*s^2 + ... + pS4*s^10 * and * | pzero(x)-1-R/S | <= 2 ** ( -60.26) */ static const float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.0000000000e+00, /* 0x00000000 */ -7.0312500000e-02, /* 0xbd900000 */ -8.0816707611e+00, /* 0xc1014e86 */ -2.5706311035e+02, /* 0xc3808814 */ -2.4852163086e+03, /* 0xc51b5376 */ -5.2530439453e+03, /* 0xc5a4285a */ }; static const float pS8[5] = { 1.1653436279e+02, /* 0x42e91198 */ 3.8337448730e+03, /* 0x456f9beb */ 4.0597855469e+04, /* 0x471e95db */ 1.1675296875e+05, /* 0x47e4087c */ 4.7627726562e+04, /* 0x473a0bba */ }; static const float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -1.1412546255e-11, /* 0xad48c58a */ -7.0312492549e-02, /* 0xbd8fffff */ -4.1596107483e+00, /* 0xc0851b88 */ -6.7674766541e+01, /* 0xc287597b */ -3.3123129272e+02, /* 0xc3a59d9b */ -3.4643338013e+02, /* 0xc3ad3779 */ }; static const float pS5[5] = { 6.0753936768e+01, /* 0x42730408 */ 1.0512523193e+03, /* 0x44836813 */ 5.9789707031e+03, /* 0x45bad7c4 */ 9.6254453125e+03, /* 0x461665c8 */ 2.4060581055e+03, /* 0x451660ee */ }; static const float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -2.5470459075e-09, /* 0xb12f081b */ -7.0311963558e-02, /* 0xbd8fffb8 */ -2.4090321064e+00, /* 0xc01a2d95 */ -2.1965976715e+01, /* 0xc1afba52 */ -5.8079170227e+01, /* 0xc2685112 */ -3.1447946548e+01, /* 0xc1fb9565 */ }; static const float pS3[5] = { 3.5856033325e+01, /* 0x420f6c94 */ 3.6151397705e+02, /* 0x43b4c1ca */ 1.1936077881e+03, /* 0x44953373 */ 1.1279968262e+03, /* 0x448cffe6 */ 1.7358093262e+02, /* 0x432d94b8 */ }; static const float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -8.8753431271e-08, /* 0xb3be98b7 */ -7.0303097367e-02, /* 0xbd8ffb12 */ -1.4507384300e+00, /* 0xbfb9b1cc */ -7.6356959343e+00, /* 0xc0f4579f */ -1.1193166733e+01, /* 0xc1331736 */ -3.2336456776e+00, /* 0xc04ef40d */ }; static const float pS2[5] = { 2.2220300674e+01, /* 0x41b1c32d */ 1.3620678711e+02, /* 0x430834f0 */ 2.7047027588e+02, /* 0x43873c32 */ 1.5387539673e+02, /* 0x4319e01a */ 1.4657617569e+01, /* 0x416a859a */ }; static __inline float pzerof(float x) { const float *p,*q; float z,r,s; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x41000000) {p = pR8; q= pS8;} else if(ix>=0x409173eb){p = pR5; q= pS5;} else if(ix>=0x4036d917){p = pR3; q= pS3;} else {p = pR2; q= pS2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qzero is * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. * We approximate pzero by * qzero(x) = s*(-1.25 + (R/S)) * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 * S = 1 + qS0*s^2 + ... + qS5*s^12 * and * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) */ static const float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.0000000000e+00, /* 0x00000000 */ 7.3242187500e-02, /* 0x3d960000 */ 1.1768206596e+01, /* 0x413c4a93 */ 5.5767340088e+02, /* 0x440b6b19 */ 8.8591972656e+03, /* 0x460a6cca */ 3.7014625000e+04, /* 0x471096a0 */ }; static const float qS8[6] = { 1.6377603149e+02, /* 0x4323c6aa */ 8.0983447266e+03, /* 0x45fd12c2 */ 1.4253829688e+05, /* 0x480b3293 */ 8.0330925000e+05, /* 0x49441ed4 */ 8.4050156250e+05, /* 0x494d3359 */ -3.4389928125e+05, /* 0xc8a7eb69 */ }; static const float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ 1.8408595828e-11, /* 0x2da1ec79 */ 7.3242180049e-02, /* 0x3d95ffff */ 5.8356351852e+00, /* 0x40babd86 */ 1.3511157227e+02, /* 0x43071c90 */ 1.0272437744e+03, /* 0x448067cd */ 1.9899779053e+03, /* 0x44f8bf4b */ }; static const float qS5[6] = { 8.2776611328e+01, /* 0x42a58da0 */ 2.0778142090e+03, /* 0x4501dd07 */ 1.8847289062e+04, /* 0x46933e94 */ 5.6751113281e+04, /* 0x475daf1d */ 3.5976753906e+04, /* 0x470c88c1 */ -5.3543427734e+03, /* 0xc5a752be */ }; static const float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ 4.3774099900e-09, /* 0x3196681b */ 7.3241114616e-02, /* 0x3d95ff70 */ 3.3442313671e+00, /* 0x405607e3 */ 4.2621845245e+01, /* 0x422a7cc5 */ 1.7080809021e+02, /* 0x432acedf */ 1.6673394775e+02, /* 0x4326bbe4 */ }; static const float qS3[6] = { 4.8758872986e+01, /* 0x42430916 */ 7.0968920898e+02, /* 0x44316c1c */ 3.7041481934e+03, /* 0x4567825f */ 6.4604252930e+03, /* 0x45c9e367 */ 2.5163337402e+03, /* 0x451d4557 */ -1.4924745178e+02, /* 0xc3153f59 */ }; static const float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ 1.5044444979e-07, /* 0x342189db */ 7.3223426938e-02, /* 0x3d95f62a */ 1.9981917143e+00, /* 0x3fffc4bf */ 1.4495602608e+01, /* 0x4167edfd */ 3.1666231155e+01, /* 0x41fd5471 */ 1.6252708435e+01, /* 0x4182058c */ }; static const float qS2[6] = { 3.0365585327e+01, /* 0x41f2ecb8 */ 2.6934811401e+02, /* 0x4386ac8f */ 8.4478375244e+02, /* 0x44533229 */ 8.8293585205e+02, /* 0x445cbbe5 */ 2.1266638184e+02, /* 0x4354aa98 */ -5.3109550476e+00, /* 0xc0a9f358 */ }; static __inline float qzerof(float x) { static const float eighth = 0.125; const float *p,*q; float s,r,z; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x41000000) {p = qR8; q= qS8;} else if(ix>=0x409173eb){p = qR5; q= qS5;} else if(ix>=0x4036d917){p = qR3; q= qS3;} else {p = qR2; q= qS2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return (r/s-eighth)/x; } diff --git a/lib/msun/src/e_j1.c b/lib/msun/src/e_j1.c index 7c7812325cc2..8c092c639bea 100644 --- a/lib/msun/src/e_j1.c +++ b/lib/msun/src/e_j1.c @@ -1,381 +1,380 @@ /* @(#)e_j1.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* j1(x), y1(x) * Bessel function of the first and second kinds of order zero. * Method -- j1(x): * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... * 2. Reduce x to |x| since j1(x)=-j1(-x), and * for x in (0,2) * j1(x) = x/2 + x*z*R0/S0, where z = x*x; * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) * for x in (2,inf) * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) * as follow: * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (sin(x) + cos(x)) * (To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one.) * * 3 Special cases * j1(nan)= nan * j1(0) = 0 * j1(inf) = 0 * * Method -- y1(x): * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN * 2. For x<2. * Since * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. * We use the following function to approximate y1, * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 * where for x in [0,2] (abs err less than 2**-65.89) * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 * Note: For tiny x, 1/x dominate y1 and hence * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) * 3. For x>=2. * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) * by method mentioned above. */ #include "math.h" #include "math_private.h" static __inline double pone(double), qone(double); static const volatile double vone = 1, vzero = 0; static const double huge = 1e300, one = 1.0, invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ /* R0/S0 on [0,2] */ r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ static const double zero = 0.0; double j1(double x) { double z, s,c,ss,cc,r,u,v,y; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return one/x; y = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincos(y, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure y+y not overflow */ z = cos(y+y); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) */ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y); else { u = pone(y); v = qone(y); z = invsqrtpi*(u*cc-v*ss)/sqrt(y); } if(hx<0) return -z; else return z; } if(ix<0x3e400000) { /* |x|<2**-27 */ if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ } z = x*x; r = z*(r00+z*(r01+z*(r02+z*r03))); s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); r *= x; return(x*0.5+r/s); } static const double U0[5] = { -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ }; static const double V0[5] = { 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ }; double y1(double x) { double z, s,c,ss,cc,u,v; int32_t hx,ix,lx; EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; /* * y1(NaN) = NaN. * y1(Inf) = 0. * y1(-Inf) = NaN and raise invalid exception. */ if(ix>=0x7ff00000) return vone/(x+x*x); /* y1(+-0) = -inf and raise divide-by-zero exception. */ if((ix|lx)==0) return -one/vzero; /* y1(x<0) = NaN and raise invalid exception. */ if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincos(x, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = cos(x+x); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) * where x0 = x-3pi/4 * Better formula: * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (cos(x) + sin(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x); else { u = pone(x); v = qone(x); z = invsqrtpi*(u*ss+v*cc)/sqrt(x); } return z; } if(ix<=0x3c900000) { /* x < 2**-54 */ return(-tpi/x); } z = x*x; u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); return(x*(u/v) + tpi*(j1(x)*log(x)-one/x)); } /* For x >= 8, the asymptotic expansions of pone is * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. * We approximate pone by * pone(x) = 1 + (R/S) * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 * S = 1 + ps0*s^2 + ... + ps4*s^10 * and * | pone(x)-1-R/S | <= 2 ** ( -60.06) */ static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ }; static const double ps8[5] = { 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ }; static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ }; static const double ps5[5] = { 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ }; static const double pr3[6] = { 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ }; static const double ps3[5] = { 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ }; static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ }; static const double ps2[5] = { 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ }; static __inline double pone(double x) { const double *p,*q; double z,r,s; int32_t ix; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x40200000) {p = pr8; q= ps8;} else if(ix>=0x40122E8B){p = pr5; q= ps5;} else if(ix>=0x4006DB6D){p = pr3; q= ps3;} else {p = pr2; q= ps2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qone is * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. * We approximate pone by * qone(x) = s*(0.375 + (R/S)) * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 * S = 1 + qs1*s^2 + ... + qs6*s^12 * and * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) */ static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ }; static const double qs8[6] = { 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ }; static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ }; static const double qs5[6] = { 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ }; static const double qr3[6] = { -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ }; static const double qs3[6] = { 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ }; static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ }; static const double qs2[6] = { 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ }; static __inline double qone(double x) { const double *p,*q; double s,r,z; int32_t ix; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x40200000) {p = qr8; q= qs8;} else if(ix>=0x40122E8B){p = qr5; q= qs5;} else if(ix>=0x4006DB6D){p = qr3; q= qs3;} else {p = qr2; q= qs2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return (.375 + r/s)/x; } diff --git a/lib/msun/src/e_j1f.c b/lib/msun/src/e_j1f.c index c022557c4d6b..28cee8e37479 100644 --- a/lib/msun/src/e_j1f.c +++ b/lib/msun/src/e_j1f.c @@ -1,336 +1,335 @@ /* e_j1f.c -- float version of e_j1.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_j1.c for complete comments. */ #include "math.h" #include "math_private.h" static __inline float ponef(float), qonef(float); static const volatile float vone = 1, vzero = 0; static const float huge = 1e30, one = 1.0, invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */ tpi = 6.3661974669e-01, /* 0x3f22f983 */ /* R0/S0 on [0,2] */ r00 = -6.2500000000e-02, /* 0xbd800000 */ r01 = 1.4070566976e-03, /* 0x3ab86cfd */ r02 = -1.5995563444e-05, /* 0xb7862e36 */ r03 = 4.9672799207e-08, /* 0x335557d2 */ s01 = 1.9153760746e-02, /* 0x3c9ce859 */ s02 = 1.8594678841e-04, /* 0x3942fab6 */ s03 = 1.1771846857e-06, /* 0x359dffc2 */ s04 = 5.0463624390e-09, /* 0x31ad6446 */ s05 = 1.2354227016e-11; /* 0x2d59567e */ static const float zero = 0.0; float j1f(float x) { float z, s,c,ss,cc,r,u,v,y; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) return one/x; y = fabsf(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincosf(y, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure y+y not overflow */ z = cosf(y+y); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) */ if(ix>0x58000000) z = (invsqrtpi*cc)/sqrtf(y); /* |x|>2**49 */ else { u = ponef(y); v = qonef(y); z = invsqrtpi*(u*cc-v*ss)/sqrtf(y); } if(hx<0) return -z; else return z; } if(ix<0x39000000) { /* |x|<2**-13 */ if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */ } z = x*x; r = z*(r00+z*(r01+z*(r02+z*r03))); s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); r *= x; return(x*(float)0.5+r/s); } static const float U0[5] = { -1.9605709612e-01, /* 0xbe48c331 */ 5.0443872809e-02, /* 0x3d4e9e3c */ -1.9125689287e-03, /* 0xbafaaf2a */ 2.3525259166e-05, /* 0x37c5581c */ -9.1909917899e-08, /* 0xb3c56003 */ }; static const float V0[5] = { 1.9916731864e-02, /* 0x3ca3286a */ 2.0255257550e-04, /* 0x3954644b */ 1.3560879779e-06, /* 0x35b602d4 */ 6.2274145840e-09, /* 0x31d5f8eb */ 1.6655924903e-11, /* 0x2d9281cf */ }; float y1f(float x) { float z, s,c,ss,cc,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; if(ix>=0x7f800000) return vone/(x+x*x); if(ix==0) return -one/vzero; if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ sincosf(x, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure x+x not overflow */ z = cosf(x+x); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) * where x0 = x-3pi/4 * Better formula: * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (cos(x) + sin(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ if(ix>0x58000000) z = (invsqrtpi*ss)/sqrtf(x); /* |x|>2**49 */ else { u = ponef(x); v = qonef(x); z = invsqrtpi*(u*ss+v*cc)/sqrtf(x); } return z; } if(ix<=0x33000000) { /* x < 2**-25 */ return(-tpi/x); } z = x*x; u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); return(x*(u/v) + tpi*(j1f(x)*logf(x)-one/x)); } /* For x >= 8, the asymptotic expansions of pone is * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. * We approximate pone by * pone(x) = 1 + (R/S) * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 * S = 1 + ps0*s^2 + ... + ps4*s^10 * and * | pone(x)-1-R/S | <= 2 ** ( -60.06) */ static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.0000000000e+00, /* 0x00000000 */ 1.1718750000e-01, /* 0x3df00000 */ 1.3239480972e+01, /* 0x4153d4ea */ 4.1205184937e+02, /* 0x43ce06a3 */ 3.8747453613e+03, /* 0x45722bed */ 7.9144794922e+03, /* 0x45f753d6 */ }; static const float ps8[5] = { 1.1420736694e+02, /* 0x42e46a2c */ 3.6509309082e+03, /* 0x45642ee5 */ 3.6956207031e+04, /* 0x47105c35 */ 9.7602796875e+04, /* 0x47bea166 */ 3.0804271484e+04, /* 0x46f0a88b */ }; static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ 1.3199052094e-11, /* 0x2d68333f */ 1.1718749255e-01, /* 0x3defffff */ 6.8027510643e+00, /* 0x40d9b023 */ 1.0830818176e+02, /* 0x42d89dca */ 5.1763616943e+02, /* 0x440168b7 */ 5.2871520996e+02, /* 0x44042dc6 */ }; static const float ps5[5] = { 5.9280597687e+01, /* 0x426d1f55 */ 9.9140142822e+02, /* 0x4477d9b1 */ 5.3532670898e+03, /* 0x45a74a23 */ 7.8446904297e+03, /* 0x45f52586 */ 1.5040468750e+03, /* 0x44bc0180 */ }; static const float pr3[6] = { 3.0250391081e-09, /* 0x314fe10d */ 1.1718686670e-01, /* 0x3defffab */ 3.9329774380e+00, /* 0x407bb5e7 */ 3.5119403839e+01, /* 0x420c7a45 */ 9.1055007935e+01, /* 0x42b61c2a */ 4.8559066772e+01, /* 0x42423c7c */ }; static const float ps3[5] = { 3.4791309357e+01, /* 0x420b2a4d */ 3.3676245117e+02, /* 0x43a86198 */ 1.0468714600e+03, /* 0x4482dbe3 */ 8.9081134033e+02, /* 0x445eb3ed */ 1.0378793335e+02, /* 0x42cf936c */ }; static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ 1.0771083225e-07, /* 0x33e74ea8 */ 1.1717621982e-01, /* 0x3deffa16 */ 2.3685150146e+00, /* 0x401795c0 */ 1.2242610931e+01, /* 0x4143e1bc */ 1.7693971634e+01, /* 0x418d8d41 */ 5.0735230446e+00, /* 0x40a25a4d */ }; static const float ps2[5] = { 2.1436485291e+01, /* 0x41ab7dec */ 1.2529022980e+02, /* 0x42fa9499 */ 2.3227647400e+02, /* 0x436846c7 */ 1.1767937469e+02, /* 0x42eb5bd7 */ 8.3646392822e+00, /* 0x4105d590 */ }; static __inline float ponef(float x) { const float *p,*q; float z,r,s; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x41000000) {p = pr8; q= ps8;} else if(ix>=0x409173eb){p = pr5; q= ps5;} else if(ix>=0x4036d917){p = pr3; q= ps3;} else {p = pr2; q= ps2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qone is * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. * We approximate pone by * qone(x) = s*(0.375 + (R/S)) * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 * S = 1 + qs1*s^2 + ... + qs6*s^12 * and * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) */ static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ 0.0000000000e+00, /* 0x00000000 */ -1.0253906250e-01, /* 0xbdd20000 */ -1.6271753311e+01, /* 0xc1822c8d */ -7.5960174561e+02, /* 0xc43de683 */ -1.1849806641e+04, /* 0xc639273a */ -4.8438511719e+04, /* 0xc73d3683 */ }; static const float qs8[6] = { 1.6139537048e+02, /* 0x43216537 */ 7.8253862305e+03, /* 0x45f48b17 */ 1.3387534375e+05, /* 0x4802bcd6 */ 7.1965775000e+05, /* 0x492fb29c */ 6.6660125000e+05, /* 0x4922be94 */ -2.9449025000e+05, /* 0xc88fcb48 */ }; static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -2.0897993405e-11, /* 0xadb7d219 */ -1.0253904760e-01, /* 0xbdd1fffe */ -8.0564479828e+00, /* 0xc100e736 */ -1.8366960144e+02, /* 0xc337ab6b */ -1.3731937256e+03, /* 0xc4aba633 */ -2.6124443359e+03, /* 0xc523471c */ }; static const float qs5[6] = { 8.1276550293e+01, /* 0x42a28d98 */ 1.9917987061e+03, /* 0x44f8f98f */ 1.7468484375e+04, /* 0x468878f8 */ 4.9851425781e+04, /* 0x4742bb6d */ 2.7948074219e+04, /* 0x46da5826 */ -4.7191835938e+03, /* 0xc5937978 */ }; static const float qr3[6] = { -5.0783124372e-09, /* 0xb1ae7d4f */ -1.0253783315e-01, /* 0xbdd1ff5b */ -4.6101160049e+00, /* 0xc0938612 */ -5.7847221375e+01, /* 0xc267638e */ -2.2824453735e+02, /* 0xc3643e9a */ -2.1921012878e+02, /* 0xc35b35cb */ }; static const float qs3[6] = { 4.7665153503e+01, /* 0x423ea91e */ 6.7386511230e+02, /* 0x4428775e */ 3.3801528320e+03, /* 0x45534272 */ 5.5477290039e+03, /* 0x45ad5dd5 */ 1.9031191406e+03, /* 0x44ede3d0 */ -1.3520118713e+02, /* 0xc3073381 */ }; static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -1.7838172539e-07, /* 0xb43f8932 */ -1.0251704603e-01, /* 0xbdd1f475 */ -2.7522056103e+00, /* 0xc0302423 */ -1.9663616180e+01, /* 0xc19d4f16 */ -4.2325313568e+01, /* 0xc2294d1f */ -2.1371921539e+01, /* 0xc1aaf9b2 */ }; static const float qs2[6] = { 2.9533363342e+01, /* 0x41ec4454 */ 2.5298155212e+02, /* 0x437cfb47 */ 7.5750280762e+02, /* 0x443d602e */ 7.3939318848e+02, /* 0x4438d92a */ 1.5594900513e+02, /* 0x431bf2f2 */ -4.9594988823e+00, /* 0xc09eb437 */ }; static __inline float qonef(float x) { const float *p,*q; float s,r,z; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; if(ix>=0x41000000) {p = qr8; q= qs8;} else if(ix>=0x409173eb){p = qr5; q= qs5;} else if(ix>=0x4036d917){p = qr3; q= qs3;} else {p = qr2; q= qs2;} /* ix>=0x40000000 */ z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return ((float).375 + r/s)/x; } diff --git a/lib/msun/src/e_jn.c b/lib/msun/src/e_jn.c index 9735b03429ff..e9553d2a4b5e 100644 --- a/lib/msun/src/e_jn.c +++ b/lib/msun/src/e_jn.c @@ -1,272 +1,271 @@ /* @(#)e_jn.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * jn(n, x), yn(n, x) * floating point Bessel's function of the 1st and 2nd kind * of order n * * Special cases: * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. * Note 2. About jn(n,x), yn(n,x) * For n=0, j0(x) is called. * For n=1, j1(x) is called. * For nx, a continued fraction approximation to * j(n,x)/j(n-1,x) is evaluated and then backward * recursion is used starting from a supposed value * for j(n,x). The resulting values of j(0,x) or j(1,x) are * compared with the actual values to correct the * supposed value of j(n,x). * * yn(n,x) is similar in all respects, except * that forward recursion is used for all * values of n>1. */ #include "math.h" #include "math_private.h" static const volatile double vone = 1, vzero = 0; static const double invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ static const double zero = 0.00000000000000000000e+00; double jn(int n, double x) { int32_t i,hx,ix,lx, sgn; double a, b, c, s, temp, di; double z, w; /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) * Thus, J(-n,x) = J(n,-x) */ EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; /* if J(n,NaN) is NaN */ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; if(n<0){ n = -n; x = -x; hx ^= 0x80000000; } if(n==0) return(j0(x)); if(n==1) return(j1(x)); sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ x = fabs(x); if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ b = zero; else if((double)n<=x) { /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ if(ix>=0x52D00000) { /* x > 2**302 */ /* (x >> n**2) * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Let s=sin(x), c=cos(x), * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2), then * * n sin(xn)*sqt2 cos(xn)*sqt2 * ---------------------------------- * 0 s-c c+s * 1 -s-c -c+s * 2 -s+c -c-s * 3 s+c c-s */ sincos(x, &s, &c); switch(n&3) { case 0: temp = c+s; break; case 1: temp = -c+s; break; case 2: temp = -c-s; break; case 3: temp = c-s; break; } b = invsqrtpi*temp/sqrt(x); } else { a = j0(x); b = j1(x); for(i=1;i33) /* underflow */ b = zero; else { temp = x*0.5; b = temp; for (a=one,i=2;i<=n;i++) { a *= (double)i; /* a = n! */ b *= temp; /* b = (x/2)^n */ } b = b/a; } } else { /* use backward recurrence */ /* x x^2 x^2 * J(n,x)/J(n-1,x) = ---- ------ ------ ..... * 2n - 2(n+1) - 2(n+2) * * 1 1 1 * (for large x) = ---- ------ ------ ..... * 2n 2(n+1) 2(n+2) * -- - ------ - ------ - * x x x * * Let w = 2n/x and h=2/x, then the above quotient * is equal to the continued fraction: * 1 * = ----------------------- * 1 * w - ----------------- * 1 * w+h - --------- * w+2h - ... * * To determine how many terms needed, let * Q(0) = w, Q(1) = w(w+h) - 1, * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), * When Q(k) > 1e4 good for single * When Q(k) > 1e9 good for double * When Q(k) > 1e17 good for quadruple */ /* determine k */ double t,v; double q0,q1,h,tmp; int32_t k,m; w = (n+n)/(double)x; h = 2.0/(double)x; q0 = w; z = w+h; q1 = w*z - 1.0; k=1; while(q1<1.0e9) { k += 1; z += h; tmp = z*q1 - q0; q0 = q1; q1 = tmp; } m = n+n; for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); a = t; b = one; /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) * Hence, if n*(log(2n/x)) > ... * single 8.8722839355e+01 * double 7.09782712893383973096e+02 * long double 1.1356523406294143949491931077970765006170e+04 * then recurrent value may overflow and the result is * likely underflow to zero */ tmp = n; v = two/x; tmp = tmp*log(fabs(v*tmp)); if(tmp<7.09782712893383973096e+02) { for(i=n-1,di=(double)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; } } else { for(i=n-1,di=(double)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; /* scale b to avoid spurious overflow */ if(b>1e100) { a /= b; t /= b; b = one; } } } z = j0(x); w = j1(x); if (fabs(z) >= fabs(w)) b = (t*z/b); else b = (t*w/a); } } if(sgn==1) return -b; else return b; } double yn(int n, double x) { int32_t i,hx,ix,lx; int32_t sign; double a, b, c, s, temp; EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; /* yn(n,NaN) = NaN */ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; /* yn(n,+-0) = -inf and raise divide-by-zero exception. */ if((ix|lx)==0) return -one/vzero; /* yn(n,x<0) = NaN and raise invalid exception. */ if(hx<0) return vzero/vzero; sign = 1; if(n<0){ n = -n; sign = 1 - ((n&1)<<1); } if(n==0) return(y0(x)); if(n==1) return(sign*y1(x)); if(ix==0x7ff00000) return zero; if(ix>=0x52D00000) { /* x > 2**302 */ /* (x >> n**2) * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Let s=sin(x), c=cos(x), * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2), then * * n sin(xn)*sqt2 cos(xn)*sqt2 * ---------------------------------- * 0 s-c c+s * 1 -s-c -c+s * 2 -s+c -c-s * 3 s+c c-s */ sincos(x, &s, &c); switch(n&3) { case 0: temp = s-c; break; case 1: temp = -s-c; break; case 2: temp = -s+c; break; case 3: temp = s+c; break; } b = invsqrtpi*temp/sqrt(x); } else { u_int32_t high; a = y0(x); b = y1(x); /* quit if b is -inf */ GET_HIGH_WORD(high,b); for(i=1;i0) return b; else return -b; } diff --git a/lib/msun/src/e_jnf.c b/lib/msun/src/e_jnf.c index 2eadaa1cc07b..b55eaf56679a 100644 --- a/lib/msun/src/e_jnf.c +++ b/lib/msun/src/e_jnf.c @@ -1,202 +1,201 @@ /* e_jnf.c -- float version of e_jn.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_jn.c for complete comments. */ #include "math.h" #include "math_private.h" static const volatile float vone = 1, vzero = 0; static const float two = 2.0000000000e+00, /* 0x40000000 */ one = 1.0000000000e+00; /* 0x3F800000 */ static const float zero = 0.0000000000e+00; float jnf(int n, float x) { int32_t i,hx,ix, sgn; float a, b, temp, di; float z, w; /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) * Thus, J(-n,x) = J(n,-x) */ GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; /* if J(n,NaN) is NaN */ if(ix>0x7f800000) return x+x; if(n<0){ n = -n; x = -x; hx ^= 0x80000000; } if(n==0) return(j0f(x)); if(n==1) return(j1f(x)); sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ x = fabsf(x); if(ix==0||ix>=0x7f800000) /* if x is 0 or inf */ b = zero; else if((float)n<=x) { /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ a = j0f(x); b = j1f(x); for(i=1;i33) /* underflow */ b = zero; else { temp = x*(float)0.5; b = temp; for (a=one,i=2;i<=n;i++) { a *= (float)i; /* a = n! */ b *= temp; /* b = (x/2)^n */ } b = b/a; } } else { /* use backward recurrence */ /* x x^2 x^2 * J(n,x)/J(n-1,x) = ---- ------ ------ ..... * 2n - 2(n+1) - 2(n+2) * * 1 1 1 * (for large x) = ---- ------ ------ ..... * 2n 2(n+1) 2(n+2) * -- - ------ - ------ - * x x x * * Let w = 2n/x and h=2/x, then the above quotient * is equal to the continued fraction: * 1 * = ----------------------- * 1 * w - ----------------- * 1 * w+h - --------- * w+2h - ... * * To determine how many terms needed, let * Q(0) = w, Q(1) = w(w+h) - 1, * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), * When Q(k) > 1e4 good for single * When Q(k) > 1e9 good for double * When Q(k) > 1e17 good for quadruple */ /* determine k */ float t,v; float q0,q1,h,tmp; int32_t k,m; w = (n+n)/(float)x; h = (float)2.0/(float)x; q0 = w; z = w+h; q1 = w*z - (float)1.0; k=1; while(q1<(float)1.0e9) { k += 1; z += h; tmp = z*q1 - q0; q0 = q1; q1 = tmp; } m = n+n; for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); a = t; b = one; /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) * Hence, if n*(log(2n/x)) > ... * single 8.8722839355e+01 * double 7.09782712893383973096e+02 * long double 1.1356523406294143949491931077970765006170e+04 * then recurrent value may overflow and the result is * likely underflow to zero */ tmp = n; v = two/x; tmp = tmp*logf(fabsf(v*tmp)); if(tmp<(float)8.8721679688e+01) { for(i=n-1,di=(float)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; } } else { for(i=n-1,di=(float)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; /* scale b to avoid spurious overflow */ if(b>(float)1e10) { a /= b; t /= b; b = one; } } } z = j0f(x); w = j1f(x); if (fabsf(z) >= fabsf(w)) b = (t*z/b); else b = (t*w/a); } } if(sgn==1) return -b; else return b; } float ynf(int n, float x) { int32_t i,hx,ix,ib; int32_t sign; float a, b, temp; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; if(ix>0x7f800000) return x+x; if(ix==0) return -one/vzero; if(hx<0) return vzero/vzero; sign = 1; if(n<0){ n = -n; sign = 1 - ((n&1)<<1); } if(n==0) return(y0f(x)); if(n==1) return(sign*y1f(x)); if(ix==0x7f800000) return zero; a = y0f(x); b = y1f(x); /* quit if b is -inf */ GET_FLOAT_WORD(ib,b); for(i=1;i0) return b; else return -b; } diff --git a/lib/msun/src/e_lgamma.c b/lib/msun/src/e_lgamma.c index 1d74db1c6af8..e5eccc89d4ea 100644 --- a/lib/msun/src/e_lgamma.c +++ b/lib/msun/src/e_lgamma.c @@ -1,37 +1,36 @@ /* @(#)e_lgamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ -#include /* lgamma(x) * Return the logarithm of the Gamma function of x. * * Method: call lgamma_r */ #include #include "math.h" #include "math_private.h" extern int signgam; double lgamma(double x) { return lgamma_r(x,&signgam); } #if (LDBL_MANT_DIG == 53) __weak_reference(lgamma, lgammal); #endif diff --git a/lib/msun/src/e_lgamma_r.c b/lib/msun/src/e_lgamma_r.c index 38efe4385631..f25c9cc04c78 100644 --- a/lib/msun/src/e_lgamma_r.c +++ b/lib/msun/src/e_lgamma_r.c @@ -1,301 +1,300 @@ /* @(#)e_lgamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* lgamma_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function * with user provide pointer for the sign of Gamma(x). * * Method: * 1. Argument Reduction for 0 < x <= 8 * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may * reduce x to a number in [1.5,2.5] by * lgamma(1+s) = log(s) + lgamma(s) * for example, * lgamma(7.3) = log(6.3) + lgamma(6.3) * = log(6.3*5.3) + lgamma(5.3) * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) * 2. Polynomial approximation of lgamma around its * minimum ymin=1.461632144968362245 to maintain monotonicity. * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use * Let z = x-ymin; * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) * where * poly(z) is a 14 degree polynomial. * 2. Rational approximation in the primary interval [2,3] * We use the following approximation: * s = x-2.0; * lgamma(x) = 0.5*s + s*P(s)/Q(s) * with accuracy * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 * Our algorithms are based on the following observation * * zeta(2)-1 2 zeta(3)-1 3 * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... * 2 3 * * where Euler = 0.5771... is the Euler constant, which is very * close to 0.5. * * 3. For x>=8, we have * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... * (better formula: * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) * Let z = 1/x, then we approximation * f(z) = lgamma(x) - (x-0.5)(log(x)-1) * by * 3 5 11 * w = w0 + w1*z + w2*z + w3*z + ... + w6*z * where * |w - f(z)| < 2**-58.74 * * 4. For negative x, since (G is gamma function) * -x*G(-x)*G(x) = pi/sin(pi*x), * we have * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 * Hence, for x<0, signgam = sign(sin(pi*x)) and * lgamma(x) = log(|Gamma(x)|) * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); * Note: one should avoid compute pi*(-x) directly in the * computation of sin(pi*(-x)). * * 5. Special Cases * lgamma(2+s) ~ s*(1-Euler) for tiny s * lgamma(1) = lgamma(2) = 0 * lgamma(x) ~ -log(|x|) for tiny x * lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero * lgamma(inf) = inf * lgamma(-inf) = inf (bug for bug compatible with C99!?) */ #include #include "math.h" #include "math_private.h" static const volatile double vzero = 0; static const double zero= 0.00000000000000000000e+00, half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ /* tt = -(tail of tf) */ tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ /* * Compute sin(pi*x) without actually doing the pi*x multiplication. * sin_pi(x) is only called for x < 0 and |x| < 2**(p-1) where p is * the precision of x. */ static double sin_pi(double x) { volatile double vz; double y,z; int n; y = -x; vz = y+0x1p52; /* depend on 0 <= y < 0x1p52 */ z = vz-0x1p52; /* rint(y) for the above range */ if (z == y) return zero; vz = y+0x1p50; GET_LOW_WORD(n,vz); /* bits for rounded y (units 0.25) */ z = vz-0x1p50; /* y rounded to a multiple of 0.25 */ if (z > y) { z -= 0.25; /* adjust to round down */ n--; } n &= 7; /* octant of y mod 2 */ y = y - z + n * 0.25; /* y mod 2 */ switch (n) { case 0: y = __kernel_sin(pi*y,zero,0); break; case 1: case 2: y = __kernel_cos(pi*(0.5-y),zero); break; case 3: case 4: y = __kernel_sin(pi*(one-y),zero,0); break; case 5: case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; default: y = __kernel_sin(pi*(y-2.0),zero,0); break; } return -y; } double lgamma_r(double x, int *signgamp) { double nadj,p,p1,p2,p3,q,r,t,w,y,z; int32_t hx; int i,ix,lx; EXTRACT_WORDS(hx,lx,x); /* purge +-Inf and NaNs */ *signgamp = 1; ix = hx&0x7fffffff; if(ix>=0x7ff00000) return x*x; /* purge +-0 and tiny arguments */ *signgamp = 1-2*((uint32_t)hx>>31); if(ix<0x3c700000) { /* |x|<2**-56, return -log(|x|) */ if((ix|lx)==0) return one/vzero; return -log(fabs(x)); } /* purge negative integers and start evaluation for other x < 0 */ if(hx<0) { *signgamp = 1; if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ return one/vzero; t = sin_pi(x); if(t==zero) return one/vzero; /* -integer */ nadj = log(pi/fabs(t*x)); if(t=0x3FE76944) {y = one-x; i= 0;} else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;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-y/2; 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 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); r += p1/p2-y/2; } } /* x < 8.0 */ else if(ix<0x40200000) { i = x; y = x-i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); r = y/2+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+6); /* FALLTHRU */ case 6: z *= (y+5); /* FALLTHRU */ case 5: z *= (y+4); /* FALLTHRU */ case 4: z *= (y+3); /* FALLTHRU */ case 3: z *= (y+2); /* FALLTHRU */ r += log(z); break; } /* 8.0 <= x < 2**56 */ } else if (ix < 0x43700000) { t = log(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); r = (x-half)*(t-one)+w; } else /* 2**56 <= x <= inf */ r = x*(log(x)-one); if(hx<0) r = nadj - r; return r; } #if (LDBL_MANT_DIG == 53) __weak_reference(lgamma_r, lgammal_r); #endif diff --git a/lib/msun/src/e_lgammaf.c b/lib/msun/src/e_lgammaf.c index b3073557c92d..cc34e440e398 100644 --- a/lib/msun/src/e_lgammaf.c +++ b/lib/msun/src/e_lgammaf.c @@ -1,32 +1,31 @@ /* e_lgammaf.c -- float version of e_lgamma.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* lgammaf(x) * Return the logarithm of the Gamma function of x. * * Method: call lgammaf_r */ #include "math.h" #include "math_private.h" extern int signgam; float lgammaf(float x) { return lgammaf_r(x,&signgam); } diff --git a/lib/msun/src/e_lgammaf_r.c b/lib/msun/src/e_lgammaf_r.c index 86f554f3bd38..3f863ce77a51 100644 --- a/lib/msun/src/e_lgammaf_r.c +++ b/lib/msun/src/e_lgammaf_r.c @@ -1,213 +1,212 @@ /* e_lgammaf_r.c -- float version of e_lgamma_r.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Conversion to float fixed By Steven G. Kargl. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const volatile float vzero = 0; static const float zero= 0, half= 0.5, one = 1, pi = 3.1415927410e+00, /* 0x40490fdb */ /* * Domain y in [0x1p-27, 0.27], range ~[-3.4599e-10, 3.4590e-10]: * |(lgamma(2 - y) + 0.5 * y) / y - a(y)| < 2**-31.4 */ a0 = 7.72156641e-02, /* 0x3d9e233f */ a1 = 3.22467119e-01, /* 0x3ea51a69 */ a2 = 6.73484802e-02, /* 0x3d89ee00 */ a3 = 2.06395667e-02, /* 0x3ca9144f */ a4 = 6.98275631e-03, /* 0x3be4cf9b */ a5 = 4.11768444e-03, /* 0x3b86eda4 */ /* * Domain x in [tc-0.24, tc+0.28], range ~[-5.6577e-10, 5.5677e-10]: * |(lgamma(x) - tf) - t(x - tc)| < 2**-30.8. */ tc = 1.46163213e+00, /* 0x3fbb16c3 */ tf = -1.21486291e-01, /* 0xbdf8cdce */ t0 = -2.94064460e-11, /* 0xae0154b7 */ t1 = -2.35939837e-08, /* 0xb2caabb8 */ t2 = 4.83836412e-01, /* 0x3ef7b968 */ t3 = -1.47586212e-01, /* 0xbe1720d7 */ t4 = 6.46013096e-02, /* 0x3d844db1 */ t5 = -3.28450352e-02, /* 0xbd068884 */ t6 = 1.86483748e-02, /* 0x3c98c47a */ t7 = -9.89206228e-03, /* 0xbc221251 */ /* * Domain y in [-0.1, 0.232], range ~[-8.4931e-10, 8.7794e-10]: * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-31.2 */ u0 = -7.72156641e-02, /* 0xbd9e233f */ u1 = 7.36789703e-01, /* 0x3f3c9e40 */ u2 = 4.95649040e-01, /* 0x3efdc5b6 */ v1 = 1.10958421e+00, /* 0x3f8e06db */ v2 = 2.10598111e-01, /* 0x3e57a708 */ v3 = -1.02995494e-02, /* 0xbc28bf71 */ /* * Domain x in (2, 3], range ~[-5.5189e-11, 5.2317e-11]: * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-35.0 * with y = x - 2. */ s0 = -7.72156641e-02, /* 0xbd9e233f */ s1 = 2.69987404e-01, /* 0x3e8a3bca */ s2 = 1.42851010e-01, /* 0x3e124789 */ s3 = 1.19389519e-02, /* 0x3c439b98 */ r1 = 6.79650068e-01, /* 0x3f2dfd8c */ r2 = 1.16058730e-01, /* 0x3dedb033 */ r3 = 3.75673687e-03, /* 0x3b763396 */ /* * Domain z in [8, 0x1p24], range ~[-1.2640e-09, 1.2640e-09]: * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-29.6. */ w0 = 4.18938547e-01, /* 0x3ed67f1d */ w1 = 8.33332464e-02, /* 0x3daaaa9f */ w2 = -2.76129087e-03; /* 0xbb34f6c6 */ static float sin_pif(float x) { volatile float vz; float y,z; int n; y = -x; vz = y+0x1p23F; /* depend on 0 <= y < 0x1p23 */ z = vz-0x1p23F; /* rintf(y) for the above range */ if (z == y) return zero; vz = y+0x1p21F; GET_FLOAT_WORD(n,vz); /* bits for rounded y (units 0.25) */ z = vz-0x1p21F; /* y rounded to a multiple of 0.25 */ if (z > y) { z -= 0.25F; /* adjust to round down */ n--; } n &= 7; /* octant of y mod 2 */ y = y - z + n * 0.25F; /* y mod 2 */ switch (n) { case 0: y = __kernel_sindf(pi*y); break; case 1: case 2: y = __kernel_cosdf(pi*((float)0.5-y)); break; case 3: case 4: y = __kernel_sindf(pi*(one-y)); break; case 5: case 6: y = -__kernel_cosdf(pi*(y-(float)1.5)); break; default: y = __kernel_sindf(pi*(y-(float)2.0)); break; } return -y; } float lgammaf_r(float x, int *signgamp) { float nadj,p,p1,p2,q,r,t,w,y,z; int32_t hx; int i,ix; GET_FLOAT_WORD(hx,x); /* purge +-Inf and NaNs */ *signgamp = 1; ix = hx&0x7fffffff; if(ix>=0x7f800000) return x*x; /* purge +-0 and tiny arguments */ *signgamp = 1-2*((uint32_t)hx>>31); if(ix<0x32000000) { /* |x|<2**-27, return -log(|x|) */ if(ix==0) return one/vzero; return -logf(fabsf(x)); } /* purge negative integers and start evaluation for other x < 0 */ if(hx<0) { *signgamp = 1; if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */ return one/vzero; t = sin_pif(x); if(t==zero) return one/vzero; /* -integer */ nadj = logf(pi/fabsf(t*x)); if(t=0x3f3b4a20) {y = one-x; i= 0;} else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3fdda618) {y=2-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*a4); p2 = z*(a1+z*(a3+z*a5)); p = y*p1+p2; r += p-y/2; break; case 1: p = t0+y*t1+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*t7))))); r += tf + p; break; case 2: p1 = y*(u0+y*(u1+y*u2)); p2 = one+y*(v1+y*(v2+y*v3)); r += p1/p2-y/2; } } /* x < 8.0 */ else if(ix<0x41000000) { i = x; y = x-i; p = y*(s0+y*(s1+y*(s2+y*s3))); q = one+y*(r1+y*(r2+y*r3)); r = y/2+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+6); /* FALLTHRU */ case 6: z *= (y+5); /* FALLTHRU */ case 5: z *= (y+4); /* FALLTHRU */ case 4: z *= (y+3); /* FALLTHRU */ case 3: z *= (y+2); /* FALLTHRU */ r += logf(z); break; } /* 8.0 <= x < 2**27 */ } else if (ix < 0x4d000000) { t = logf(x); z = one/x; y = z*z; w = w0+z*(w1+y*w2); r = (x-half)*(t-one)+w; } else /* 2**27 <= x <= inf */ r = x*(logf(x)-one); if(hx<0) r = nadj - r; return r; } diff --git a/lib/msun/src/e_lgammal.c b/lib/msun/src/e_lgammal.c index c45a62a7268e..f7ab1ce94a53 100644 --- a/lib/msun/src/e_lgammal.c +++ b/lib/msun/src/e_lgammal.c @@ -1,23 +1,22 @@ /* @(#)e_lgamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" extern int signgam; long double lgammal(long double x) { return lgammal_r(x,&signgam); } diff --git a/lib/msun/src/e_log.c b/lib/msun/src/e_log.c index 5dff93c66c5e..0570b5bb51e5 100644 --- a/lib/msun/src/e_log.c +++ b/lib/msun/src/e_log.c @@ -1,145 +1,144 @@ /* @(#)e_log.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* log(x) * Return the logrithm of x * * Method : * 1. Argument Reduction: find k and f such that * x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * 2. Approximation of log(1+f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Reme algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s * (the values of Lg1 to Lg7 are listed in the program) * and * | 2 14 | -58.45 * | Lg1*s +...+Lg7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log(1+f) = f - s*(f - R) (if f is not too large) * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) * * 3. Finally, log(x) = k*ln2 + log(1+f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log(x) is NaN with signal if x < 0 (including -INF) ; * log(+INF) is +INF; log(0) is -INF with signal; * log(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ static const double zero = 0.0; static volatile double vzero = 0.0; double log(double x) { double hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,hx,i,j; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/vzero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ GET_HIGH_WORD(hx,x); } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ k += (i>>20); f = x-1.0; if((0x000fffff&(2+hx))<3) { /* -2**-20 <= f < 2**-20 */ if(f==zero) { if(k==0) { return zero; } else { dk=(double)k; return dk*ln2_hi+dk*ln2_lo; } } R = f*f*(0.5-0.33333333333333333*f); if(k==0) return f-R; else {dk=(double)k; return dk*ln2_hi-((R-dk*ln2_lo)-f);} } s = f/(2.0+f); dk = (double)k; z = s*s; i = hx-0x6147a; w = z*z; j = 0x6b851-hx; t1= w*(Lg2+w*(Lg4+w*Lg6)); t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); i |= j; R = t2+t1; if(i>0) { hfsq=0.5*f*f; if(k==0) return f-(hfsq-s*(hfsq+R)); else return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); } else { if(k==0) return f-s*(f-R); else return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } #if (LDBL_MANT_DIG == 53) __weak_reference(log, logl); #endif diff --git a/lib/msun/src/e_log10.c b/lib/msun/src/e_log10.c index 89efd791265d..7b1f754d9002 100644 --- a/lib/msun/src/e_log10.c +++ b/lib/msun/src/e_log10.c @@ -1,92 +1,91 @@ /* @(#)e_log10.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * Return the base 10 logarithm of x. See e_log.c and k_log.h for most * comments. * * log10(x) = (f - 0.5*f*f + k_log1p(f)) / ln10 + k * log10(2) * in not-quite-routine extra precision. */ #include #include "math.h" #include "math_private.h" #include "k_log.h" static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ ivln10hi = 4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */ ivln10lo = 2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */ log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ static const double zero = 0.0; static volatile double vzero = 0.0; double log10(double x) { double f,hfsq,hi,lo,r,val_hi,val_lo,w,y,y2; int32_t i,k,hx; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/vzero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ GET_HIGH_WORD(hx,x); } if (hx >= 0x7ff00000) return x+x; if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */ k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ k += (i>>20); y = (double)k; f = x - 1.0; hfsq = 0.5*f*f; r = k_log1p(f); /* See e_log2.c for most details. */ hi = f - hfsq; SET_LOW_WORD(hi,0); lo = (f - hi) - hfsq + r; val_hi = hi*ivln10hi; y2 = y*log10_2hi; val_lo = y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi; /* * Extra precision in for adding y*log10_2hi is not strictly needed * since there is no very large cancellation near x = sqrt(2) or * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs * with some parallelism and it reduces the error for many args. */ w = y2 + val_hi; val_lo += (y2 - w) + val_hi; val_hi = w; return val_lo + val_hi; } #if (LDBL_MANT_DIG == 53) __weak_reference(log10, log10l); #endif diff --git a/lib/msun/src/e_log10f.c b/lib/msun/src/e_log10f.c index f240d14fca27..ee01d6f5b75b 100644 --- a/lib/msun/src/e_log10f.c +++ b/lib/msun/src/e_log10f.c @@ -1,70 +1,69 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * Float version of e_log10.c. See the latter for most comments. */ #include "math.h" #include "math_private.h" #include "k_logf.h" static const float two25 = 3.3554432000e+07, /* 0x4c000000 */ ivln10hi = 4.3432617188e-01, /* 0x3ede6000 */ ivln10lo = -3.1689971365e-05, /* 0xb804ead9 */ log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */ log10_2lo = 7.9034151668e-07; /* 0x355427db */ static const float zero = 0.0; static volatile float vzero = 0.0; float log10f(float x) { float f,hfsq,hi,lo,r,y; int32_t i,k,hx; GET_FLOAT_WORD(hx,x); k=0; if (hx < 0x00800000) { /* x < 2**-126 */ if ((hx&0x7fffffff)==0) return -two25/vzero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(hx,x); } if (hx >= 0x7f800000) return x+x; if (hx == 0x3f800000) return zero; /* log(1) = +0 */ k += (hx>>23)-127; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); y = (float)k; f = x - (float)1.0; hfsq = (float)0.5*f*f; r = k_log1pf(f); /* See e_log2f.c and e_log2.c for details. */ if (sizeof(float_t) > sizeof(float)) return (r - hfsq + f) * ((float_t)ivln10lo + ivln10hi) + y * ((float_t)log10_2lo + log10_2hi); hi = f - hfsq; GET_FLOAT_WORD(hx,hi); SET_FLOAT_WORD(hi,hx&0xfffff000); lo = (f - hi) - hfsq + r; return y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi + y*log10_2hi; } diff --git a/lib/msun/src/e_log2.c b/lib/msun/src/e_log2.c index eb099171f669..331bbfecac74 100644 --- a/lib/msun/src/e_log2.c +++ b/lib/msun/src/e_log2.c @@ -1,115 +1,114 @@ /* @(#)e_log10.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * Return the base 2 logarithm of x. See e_log.c and k_log.h for most * comments. * * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel, * then does the combining and scaling steps * log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k * in not-quite-routine extra precision. */ #include #include "math.h" #include "math_private.h" #include "k_log.h" static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */ ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ static const double zero = 0.0; static volatile double vzero = 0.0; double log2(double x) { double f,hfsq,hi,lo,r,val_hi,val_lo,w,y; int32_t i,k,hx; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/vzero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ GET_HIGH_WORD(hx,x); } if (hx >= 0x7ff00000) return x+x; if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */ k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ k += (i>>20); y = (double)k; f = x - 1.0; hfsq = 0.5*f*f; r = k_log1p(f); /* * f-hfsq must (for args near 1) be evaluated in extra precision * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2). * This is fairly efficient since f-hfsq only depends on f, so can * be evaluated in parallel with R. Not combining hfsq with R also * keeps R small (though not as small as a true `lo' term would be), * so that extra precision is not needed for terms involving R. * * Compiler bugs involving extra precision used to break Dekker's * theorem for spitting f-hfsq as hi+lo, unless double_t was used * or the multi-precision calculations were avoided when double_t * has extra precision. These problems are now automatically * avoided as a side effect of the optimization of combining the * Dekker splitting step with the clear-low-bits step. * * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra * precision to avoid a very large cancellation when x is very near * these values. Unlike the above cancellations, this problem is * specific to base 2. It is strange that adding +-1 is so much * harder than adding +-ln2 or +-log10_2. * * This uses Dekker's theorem to normalize y+val_hi, so the * compiler bugs are back in some configurations, sigh. And I * don't want to used double_t to avoid them, since that gives a * pessimization and the support for avoiding the pessimization * is not yet available. * * The multi-precision calculations for the multiplications are * routine. */ hi = f - hfsq; SET_LOW_WORD(hi,0); lo = (f - hi) - hfsq + r; val_hi = hi*ivln2hi; val_lo = (lo+hi)*ivln2lo + lo*ivln2hi; /* spadd(val_hi, val_lo, y), except for not using double_t: */ w = y + val_hi; val_lo += (y - w) + val_hi; val_hi = w; return val_lo + val_hi; } #if (LDBL_MANT_DIG == 53) __weak_reference(log2, log2l); #endif diff --git a/lib/msun/src/e_log2f.c b/lib/msun/src/e_log2f.c index 7c1b5c032bdc..52fa411bae8e 100644 --- a/lib/msun/src/e_log2f.c +++ b/lib/msun/src/e_log2f.c @@ -1,80 +1,79 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * Float version of e_log2.c. See the latter for most comments. */ #include "math.h" #include "math_private.h" #include "k_logf.h" static const float two25 = 3.3554432000e+07, /* 0x4c000000 */ ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */ ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */ static const float zero = 0.0; static volatile float vzero = 0.0; float log2f(float x) { float f,hfsq,hi,lo,r,y; int32_t i,k,hx; GET_FLOAT_WORD(hx,x); k=0; if (hx < 0x00800000) { /* x < 2**-126 */ if ((hx&0x7fffffff)==0) return -two25/vzero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(hx,x); } if (hx >= 0x7f800000) return x+x; if (hx == 0x3f800000) return zero; /* log(1) = +0 */ k += (hx>>23)-127; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); y = (float)k; f = x - (float)1.0; hfsq = (float)0.5*f*f; r = k_log1pf(f); /* * We no longer need to avoid falling into the multi-precision * calculations due to compiler bugs breaking Dekker's theorem. * Keep avoiding this as an optimization. See e_log2.c for more * details (some details are here only because the optimization * is not yet available in double precision). * * Another compiler bug turned up. With gcc on i386, * (ivln2lo + ivln2hi) would be evaluated in float precision * despite runtime evaluations using double precision. So we * must cast one of its terms to float_t. This makes the whole * expression have type float_t, so return is forced to waste * time clobbering its extra precision. */ if (sizeof(float_t) > sizeof(float)) return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y; hi = f - hfsq; GET_FLOAT_WORD(hx,hi); SET_FLOAT_WORD(hi,hx&0xfffff000); lo = (f - hi) - hfsq + r; return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y; } diff --git a/lib/msun/src/e_logf.c b/lib/msun/src/e_logf.c index 2bbdd068591c..aad9db3a496c 100644 --- a/lib/msun/src/e_logf.c +++ b/lib/msun/src/e_logf.c @@ -1,87 +1,86 @@ /* e_logf.c -- float version of e_log.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ two25 = 3.355443200e+07, /* 0x4c000000 */ /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ static const float zero = 0.0; static volatile float vzero = 0.0; float logf(float x) { float hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,ix,i,j; GET_FLOAT_WORD(ix,x); k=0; if (ix < 0x00800000) { /* x < 2**-126 */ if ((ix&0x7fffffff)==0) return -two25/vzero; /* log(+-0)=-inf */ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix,x); } if (ix >= 0x7f800000) return x+x; k += (ix>>23)-127; ix &= 0x007fffff; i = (ix+(0x95f64<<3))&0x800000; SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); f = x-(float)1.0; if((0x007fffff&(0x8000+ix))<0xc000) { /* -2**-9 <= f < 2**-9 */ if(f==zero) { if(k==0) { return zero; } else { dk=(float)k; return dk*ln2_hi+dk*ln2_lo; } } R = f*f*((float)0.5-(float)0.33333333333333333*f); if(k==0) return f-R; else {dk=(float)k; return dk*ln2_hi-((R-dk*ln2_lo)-f);} } s = f/((float)2.0+f); dk = (float)k; z = s*s; i = ix-(0x6147a<<3); w = z*z; j = (0x6b851<<3)-ix; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); i |= j; R = t2+t1; if(i>0) { hfsq=(float)0.5*f*f; if(k==0) return f-(hfsq-s*(hfsq+R)); else return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); } else { if(k==0) return f-s*(f-R); else return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } diff --git a/lib/msun/src/e_pow.c b/lib/msun/src/e_pow.c index 8b62c49abe4a..5be1fec8105e 100644 --- a/lib/msun/src/e_pow.c +++ b/lib/msun/src/e_pow.c @@ -1,312 +1,311 @@ /* @(#)e_pow.c 1.5 04/04/22 SMI */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* pow(x,y) return x**y * * n * Method: Let x = 2 * (1+f) * 1. Compute and return log2(x) in two pieces: * log2(x) = w1 + w2, * where w1 has 53-24 = 29 bit trailing zeros. * 2. Perform y*log2(x) = n+y' by simulating multi-precision * arithmetic, where |y'|<=0.5. * 3. Return x**y = 2**n*exp(y'*log2) * * Special cases: * 1. (anything) ** 0 is 1 * 2. (anything) ** 1 is itself * 3. (anything) ** NAN is NAN except 1 ** NAN = 1 * 4. NAN ** (anything except 0) is NAN * 5. +-(|x| > 1) ** +INF is +INF * 6. +-(|x| > 1) ** -INF is +0 * 7. +-(|x| < 1) ** +INF is +0 * 8. +-(|x| < 1) ** -INF is +INF * 9. +-1 ** +-INF is 1 * 10. +0 ** (+anything except 0, NAN) is +0 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 * 12. +0 ** (-anything except 0, NAN) is +INF * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) * 15. +INF ** (+anything except 0,NAN) is +INF * 16. +INF ** (-anything except 0,NAN) is +0 * 17. -INF ** (anything) = -0 ** (-anything) * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) * 19. (-anything except 0 and inf) ** (non-integer) is NAN * * Accuracy: * pow(x,y) returns x**y nearly rounded. In particular * pow(integer,integer) * always returns the correct integer provided it is * representable. * * Constants : * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const double bp[] = {1.0, 1.5,}, dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ zero = 0.0, half = 0.5, qrtr = 0.25, thrd = 3.3333333333333331e-01, /* 0x3fd55555, 0x55555555 */ one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ huge = 1.0e300, tiny = 1.0e-300, /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ double pow(double x, double y) { double z,ax,z_h,z_l,p_h,p_l; double y1,t1,t2,r,s,t,u,v,w; int32_t i,j,k,yisint,n; int32_t hx,hy,ix,iy; u_int32_t lx,ly; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hy,ly,y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ if((iy|ly)==0) return one; /* x==1: 1**y = 1, even if y is NaN */ if (hx==0x3ff00000 && lx == 0) return one; /* y!=zero: result is NaN if either arg is NaN */ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) return nan_mix(x, y); /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if(hx<0) { if(iy>=0x43400000) yisint = 2; /* even integer y */ else if(iy>=0x3ff00000) { k = (iy>>20)-0x3ff; /* exponent */ if(k>20) { j = ly>>(52-k); if(((u_int32_t)j<<(52-k))==ly) yisint = 2-(j&1); } else if(ly==0) { j = iy>>(20-k); if((j<<(20-k))==iy) yisint = 2-(j&1); } } } /* special value of y */ if(ly==0) { if (iy==0x7ff00000) { /* y is +-inf */ if(((ix-0x3ff00000)|lx)==0) return one; /* (-1)**+-inf is 1 */ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ return (hy>=0)? y: zero; else /* (|x|<1)**-,+inf = inf,0 */ return (hy<0)?-y: zero; } if(iy==0x3ff00000) { /* y is +-1 */ if(hy<0) return one/x; else return x; } if(hy==0x40000000) return x*x; /* y is 2 */ if(hy==0x3fe00000) { /* y is 0.5 */ if(hx>=0) /* x >= +0 */ return sqrt(x); } } ax = fabs(x); /* special value of x */ if(lx==0) { if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ z = ax; /*x is +-0,+-inf,+-1*/ if(hy<0) z = one/z; /* z = (1/|x|) */ if(hx<0) { if(((ix-0x3ff00000)|yisint)==0) { z = (z-z)/(z-z); /* (-1)**non-int is NaN */ } else if(yisint==1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } } /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be n = (hx>>31)+1; but ANSI C says a right shift of a signed negative quantity is implementation defined. */ n = ((u_int32_t)hx>>31)-1; /* (x<0)**(non-int) is NaN */ if((n|yisint)==0) return (x-x)/(x-x); s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ /* |y| is huge */ if(iy>0x41e00000) { /* if |y| > 2**31 */ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; } /* over/underflow if x is not close to one */ if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny; if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny; /* now |1-x| is tiny <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax-one; /* t has 20 trailing zeros */ w = (t*t)*(half-t*(thrd-t*qrtr)); u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ v = t*ivln2_l-w*ivln2; t1 = u+v; SET_LOW_WORD(t1,0); t2 = v-(t1-u); } else { double ss,s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if(ix<0x00100000) {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } n += ((ix)>>20)-0x3ff; j = ix&0x000fffff; /* determine interval */ ix = j|0x3ff00000; /* normalize ix */ if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ s2 = ss*ss; r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); r += s_l*(s_h+ss); s2 = s_h*s_h; t_h = 3+s2+r; SET_LOW_WORD(t_h,0); t_l = r-((t_h-3)-s2); /* u+v = ss*(1+...) */ u = s_h*t_h; v = s_l*t_h+t_l*ss; /* 2/(3log2)*(ss+...) */ p_h = u+v; SET_LOW_WORD(p_h,0); p_l = v-(p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp+dp_l[k]; /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = n; t1 = (((z_h+z_l)+dp_h[k])+t); SET_LOW_WORD(t1,0); t2 = z_l-(((t1-t)-dp_h[k])-z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ y1 = y; SET_LOW_WORD(y1,0); p_l = (y-y1)*t1+y*t2; p_h = y1*t1; z = p_l+p_h; EXTRACT_WORDS(j,i,z); if (j>=0x40900000) { /* z >= 1024 */ if(((j-0x40900000)|i)!=0) /* if z > 1024 */ return s*huge*huge; /* overflow */ else { if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ } } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ return s*tiny*tiny; /* underflow */ else { if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ } } /* * compute 2**(p_h+p_l) */ i = j&0x7fffffff; k = (i>>20)-0x3ff; n = 0; if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ n = j+(0x00100000>>(k+1)); k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ t = zero; SET_HIGH_WORD(t,n&~(0x000fffff>>k)); n = ((n&0x000fffff)|0x00100000)>>(20-k); if(j<0) n = -n; p_h -= t; } t = p_l+p_h; SET_LOW_WORD(t,0); u = t*lg2_h; v = (p_l-(t-p_h))*lg2+t*lg2_l; z = u+v; w = v-(z-u); t = z*z; t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-two)-(w+z*w); z = one-(r-z); GET_HIGH_WORD(j,z); j += (n<<20); if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ else SET_HIGH_WORD(z,j); return s*z; } #if (LDBL_MANT_DIG == 53) __weak_reference(pow, powl); #endif diff --git a/lib/msun/src/e_powf.c b/lib/msun/src/e_powf.c index ff872ab46327..2e7c37542a77 100644 --- a/lib/msun/src/e_powf.c +++ b/lib/msun/src/e_powf.c @@ -1,250 +1,249 @@ /* e_powf.c -- float version of e_pow.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float bp[] = {1.0, 1.5,}, dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */ dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */ zero = 0.0, half = 0.5, qrtr = 0.25, thrd = 3.33333343e-01, /* 0x3eaaaaab */ one = 1.0, two = 2.0, two24 = 16777216.0, /* 0x4b800000 */ huge = 1.0e30, tiny = 1.0e-30, /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ L1 = 6.0000002384e-01, /* 0x3f19999a */ L2 = 4.2857143283e-01, /* 0x3edb6db7 */ L3 = 3.3333334327e-01, /* 0x3eaaaaab */ L4 = 2.7272811532e-01, /* 0x3e8ba305 */ L5 = 2.3066075146e-01, /* 0x3e6c3255 */ L6 = 2.0697501302e-01, /* 0x3e53f142 */ P1 = 1.6666667163e-01, /* 0x3e2aaaab */ P2 = -2.7777778450e-03, /* 0xbb360b61 */ P3 = 6.6137559770e-05, /* 0x388ab355 */ P4 = -1.6533901999e-06, /* 0xb5ddea0e */ P5 = 4.1381369442e-08, /* 0x3331bb4c */ lg2 = 6.9314718246e-01, /* 0x3f317218 */ lg2_h = 6.93145752e-01, /* 0x3f317200 */ lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */ cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */ ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ float powf(float x, float y) { float z,ax,z_h,z_l,p_h,p_l; float y1,t1,t2,r,s,sn,t,u,v,w; int32_t i,j,k,yisint,n; int32_t hx,hy,ix,iy,is; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ if(iy==0) return one; /* x==1: 1**y = 1, even if y is NaN */ if (hx==0x3f800000) return one; /* y!=zero: result is NaN if either arg is NaN */ if(ix > 0x7f800000 || iy > 0x7f800000) return nan_mix(x, y); /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if(hx<0) { if(iy>=0x4b800000) yisint = 2; /* even integer y */ else if(iy>=0x3f800000) { k = (iy>>23)-0x7f; /* exponent */ j = iy>>(23-k); if((j<<(23-k))==iy) yisint = 2-(j&1); } } /* special value of y */ if (iy==0x7f800000) { /* y is +-inf */ if (ix==0x3f800000) return one; /* (-1)**+-inf is NaN */ else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */ return (hy>=0)? y: zero; else /* (|x|<1)**-,+inf = inf,0 */ return (hy<0)?-y: zero; } if(iy==0x3f800000) { /* y is +-1 */ if(hy<0) return one/x; else return x; } if(hy==0x40000000) return x*x; /* y is 2 */ if(hy==0x3f000000) { /* y is 0.5 */ if(hx>=0) /* x >= +0 */ return sqrtf(x); } ax = fabsf(x); /* special value of x */ if(ix==0x7f800000||ix==0||ix==0x3f800000){ z = ax; /*x is +-0,+-inf,+-1*/ if(hy<0) z = one/z; /* z = (1/|x|) */ if(hx<0) { if(((ix-0x3f800000)|yisint)==0) { z = (z-z)/(z-z); /* (-1)**non-int is NaN */ } else if(yisint==1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } n = ((u_int32_t)hx>>31)-1; /* (x<0)**(non-int) is NaN */ if((n|yisint)==0) return (x-x)/(x-x); sn = one; /* s (sign of result -ve**odd) = -1 else = 1 */ if((n|(yisint-1))==0) sn = -one;/* (-ve)**(odd int) */ /* |y| is huge */ if(iy>0x4d000000) { /* if |y| > 2**27 */ /* over/underflow if x is not close to one */ if(ix<0x3f7ffff6) return (hy<0)? sn*huge*huge:sn*tiny*tiny; if(ix>0x3f800007) return (hy>0)? sn*huge*huge:sn*tiny*tiny; /* now |1-x| is tiny <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax-1; /* t has 20 trailing zeros */ w = (t*t)*(half-t*(thrd-t*qrtr)); u = ivln2_h*t; /* ivln2_h has 16 sig. bits */ v = t*ivln2_l-w*ivln2; t1 = u+v; GET_FLOAT_WORD(is,t1); SET_FLOAT_WORD(t1,is&0xfffff000); t2 = v-(t1-u); } else { float s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if(ix<0x00800000) {ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); } n += ((ix)>>23)-0x7f; j = ix&0x007fffff; /* determine interval */ ix = j|0x3f800000; /* normalize ix */ if(j<=0x1cc471) k=0; /* |x|>1)&0xfffff000)|0x20000000; SET_FLOAT_WORD(t_h,is+0x00400000+(k<<21)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ s2 = s*s; r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); r += s_l*(s_h+s); s2 = s_h*s_h; t_h = 3+s2+r; GET_FLOAT_WORD(is,t_h); SET_FLOAT_WORD(t_h,is&0xfffff000); t_l = r-((t_h-3)-s2); /* u+v = s*(1+...) */ u = s_h*t_h; v = s_l*t_h+t_l*s; /* 2/(3log2)*(s+...) */ p_h = u+v; GET_FLOAT_WORD(is,p_h); SET_FLOAT_WORD(p_h,is&0xfffff000); p_l = v-(p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp+dp_l[k]; /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = n; t1 = (((z_h+z_l)+dp_h[k])+t); GET_FLOAT_WORD(is,t1); SET_FLOAT_WORD(t1,is&0xfffff000); t2 = z_l-(((t1-t)-dp_h[k])-z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ GET_FLOAT_WORD(is,y); SET_FLOAT_WORD(y1,is&0xfffff000); p_l = (y-y1)*t1+y*t2; p_h = y1*t1; z = p_l+p_h; GET_FLOAT_WORD(j,z); if (j>0x43000000) /* if z > 128 */ return sn*huge*huge; /* overflow */ else if (j==0x43000000) { /* if z == 128 */ if(p_l+ovt>z-p_h) return sn*huge*huge; /* overflow */ } else if ((j&0x7fffffff)>0x43160000) /* z <= -150 */ return sn*tiny*tiny; /* underflow */ else if (j==0xc3160000){ /* z == -150 */ if(p_l<=z-p_h) return sn*tiny*tiny; /* underflow */ } /* * compute 2**(p_h+p_l) */ i = j&0x7fffffff; k = (i>>23)-0x7f; n = 0; if(i>0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */ n = j+(0x00800000>>(k+1)); k = ((n&0x7fffffff)>>23)-0x7f; /* new k for n */ SET_FLOAT_WORD(t,n&~(0x007fffff>>k)); n = ((n&0x007fffff)|0x00800000)>>(23-k); if(j<0) n = -n; p_h -= t; } t = p_l+p_h; GET_FLOAT_WORD(is,t); SET_FLOAT_WORD(t,is&0xffff8000); u = t*lg2_h; v = (p_l-(t-p_h))*lg2+t*lg2_l; z = u+v; w = v-(z-u); t = z*z; t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-two)-(w+z*w); z = one-(r-z); GET_FLOAT_WORD(j,z); j += (n<<23); if((j>>23)<=0) z = scalbnf(z,n); /* subnormal output */ else SET_FLOAT_WORD(z,j); return sn*z; } diff --git a/lib/msun/src/e_rem_pio2.c b/lib/msun/src/e_rem_pio2.c index ef4107af94cb..266ab24097f2 100644 --- a/lib/msun/src/e_rem_pio2.c +++ b/lib/msun/src/e_rem_pio2.c @@ -1,178 +1,177 @@ /* @(#)e_rem_pio2.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * Optimized by Bruce D. Evans. */ -#include /* __ieee754_rem_pio2(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __kernel_rem_pio2() */ #include #include "math.h" #include "math_private.h" /* * invpio2: 53 bits of 2/pi * pio2_1: first 33 bit of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 33 bit of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 33 bit of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ #ifdef INLINE_REM_PIO2 static __inline __always_inline #endif int __ieee754_rem_pio2(double x, double *y) { double z,w,t,r,fn; double tx[3],ty[2]; int32_t e0,i,j,nx,n,ix,hx; u_int32_t low; GET_HIGH_WORD(hx,x); /* high word of x */ ix = hx&0x7fffffff; #if 0 /* Must be handled in caller. */ if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ {y[0] = x; y[1] = 0; return 0;} #endif if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ goto medium; /* cancellation -- use medium case */ if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ if (hx > 0) { z = x - pio2_1; /* one round good to 85 bits */ y[0] = z - pio2_1t; y[1] = (z-y[0])-pio2_1t; return 1; } else { z = x + pio2_1; y[0] = z + pio2_1t; y[1] = (z-y[0])+pio2_1t; return -1; } } else { if (hx > 0) { z = x - 2*pio2_1; y[0] = z - 2*pio2_1t; y[1] = (z-y[0])-2*pio2_1t; return 2; } else { z = x + 2*pio2_1; y[0] = z + 2*pio2_1t; y[1] = (z-y[0])+2*pio2_1t; return -2; } } } if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ goto medium; if (hx > 0) { z = x - 3*pio2_1; y[0] = z - 3*pio2_1t; y[1] = (z-y[0])-3*pio2_1t; return 3; } else { z = x + 3*pio2_1; y[0] = z + 3*pio2_1t; y[1] = (z-y[0])+3*pio2_1t; return -3; } } else { if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ goto medium; if (hx > 0) { z = x - 4*pio2_1; y[0] = z - 4*pio2_1t; y[1] = (z-y[0])-4*pio2_1t; return 4; } else { z = x + 4*pio2_1; y[0] = z + 4*pio2_1t; y[1] = (z-y[0])+4*pio2_1t; return -4; } } } if(ix<0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ medium: fn = rnint((double_t)x*invpio2); n = irint(fn); r = x-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 85 bit */ { u_int32_t high; j = ix>>20; y[0] = r-w; GET_HIGH_WORD(high,y[0]); i = j-((high>>20)&0x7ff); if(i>16) { /* 2nd iteration needed, good to 118 */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; GET_HIGH_WORD(high,y[0]); i = j-((high>>20)&0x7ff); if(i>49) { /* 3rd iteration need, 151 bits acc */ t = r; /* will cover all possible cases */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); y[0] = r-w; } } } y[1] = (r-y[0])-w; return n; } /* * all other (large) arguments */ if(ix>=0x7ff00000) { /* x is inf or NaN */ y[0]=y[1]=x-x; return 0; } /* set z = scalbn(|x|,ilogb(x)-23) */ GET_LOW_WORD(low,x); e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ INSERT_WORDS(z, ix - ((int32_t)(e0<<20)), low); for(i=0;i<2;i++) { tx[i] = (double)((int32_t)(z)); z = (z-tx[i])*two24; } tx[2] = z; nx = 3; while(tx[nx-1]==zero) nx--; /* skip zero term */ n = __kernel_rem_pio2(tx,ty,e0,nx,1); if(hx<0) {y[0] = -ty[0]; y[1] = -ty[1]; return -n;} y[0] = ty[0]; y[1] = ty[1]; return n; } diff --git a/lib/msun/src/e_rem_pio2f.c b/lib/msun/src/e_rem_pio2f.c index 26f6bc85791b..744060f18010 100644 --- a/lib/msun/src/e_rem_pio2f.c +++ b/lib/msun/src/e_rem_pio2f.c @@ -1,76 +1,75 @@ /* e_rem_pio2f.c -- float version of e_rem_pio2.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Debugged and optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* __ieee754_rem_pio2f(x,y) * * return the remainder of x rem pi/2 in *y * use double precision for everything except passing x * use __kernel_rem_pio2() for large x */ #include #include "math.h" #include "math_private.h" /* * invpio2: 53 bits of 2/pi * pio2_1: first 25 bits of pi/2 * pio2_1t: pi/2 - pio2_1 */ static const double invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */ pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ #ifdef INLINE_REM_PIO2F static __inline __always_inline #endif int __ieee754_rem_pio2f(float x, double *y) { double w,r,fn; double tx[1],ty[1]; float z; int32_t e0,n,ix,hx; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; /* 33+53 bit pi is good enough for medium size */ if(ix<0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ fn = rnint((float_t)x*invpio2); n = irint(fn); r = x-fn*pio2_1; w = fn*pio2_1t; *y = r-w; return n; } /* * all other (large) arguments */ if(ix>=0x7f800000) { /* x is inf or NaN */ *y=x-x; return 0; } /* set z = scalbn(|x|,ilogb(|x|)-23) */ e0 = (ix>>23)-150; /* e0 = ilogb(|x|)-23; */ SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23))); tx[0] = z; n = __kernel_rem_pio2(tx,ty,e0,1,0); if(hx<0) {*y = -ty[0]; return -n;} *y = ty[0]; return n; } diff --git a/lib/msun/src/e_remainder.c b/lib/msun/src/e_remainder.c index bd1ce8950619..406f12c14c2f 100644 --- a/lib/msun/src/e_remainder.c +++ b/lib/msun/src/e_remainder.c @@ -1,77 +1,76 @@ /* @(#)e_remainder.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* remainder(x,p) * Return : * returns x REM p = x - [x/p]*p as if in infinite * precise arithmetic, where [x/p] is the (infinite bit) * integer nearest x/p (in half way case choose the even one). * Method : * Based on fmod() return x-[x/p]chopped*p exactlp. */ #include #include "math.h" #include "math_private.h" static const double zero = 0.0; double remainder(double x, double p) { int32_t hx,hp; u_int32_t sx,lx,lp; double p_half; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hp,lp,p); sx = hx&0x80000000; hp &= 0x7fffffff; hx &= 0x7fffffff; /* purge off exception values */ if(((hp|lp)==0)|| /* p = 0 */ (hx>=0x7ff00000)|| /* x not finite */ ((hp>=0x7ff00000)&& /* p is NaN */ (((hp-0x7ff00000)|lp)!=0))) return nan_mix_op(x, p, *)/nan_mix_op(x, p, *); if (hp<=0x7fdfffff) x = fmod(x,p+p); /* now x < 2p */ if (((hx-hp)|(lx-lp))==0) return zero*x; x = fabs(x); p = fabs(p); if (hp<0x00200000) { if(x+x>p) { x-=p; if(x+x>=p) x -= p; } } else { p_half = 0.5*p; if(x>p_half) { x-=p; if(x>=p_half) x -= p; } } GET_HIGH_WORD(hx,x); if ((hx&0x7fffffff)==0) hx = 0; SET_HIGH_WORD(x,hx^sx); return x; } #if LDBL_MANT_DIG == 53 __weak_reference(remainder, remainderl); #endif diff --git a/lib/msun/src/e_remainderf.c b/lib/msun/src/e_remainderf.c index 053ae45c4a10..4a6ff6345fcd 100644 --- a/lib/msun/src/e_remainderf.c +++ b/lib/msun/src/e_remainderf.c @@ -1,63 +1,62 @@ /* e_remainderf.c -- float version of e_remainder.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float zero = 0.0; float remainderf(float x, float p) { int32_t hx,hp; u_int32_t sx; float p_half; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hp,p); sx = hx&0x80000000; hp &= 0x7fffffff; hx &= 0x7fffffff; /* purge off exception values */ if((hp==0)|| /* p = 0 */ (hx>=0x7f800000)|| /* x not finite */ ((hp>0x7f800000))) /* p is NaN */ return nan_mix_op(x, p, *)/nan_mix_op(x, p, *); if (hp<=0x7effffff) x = fmodf(x,p+p); /* now x < 2p */ if ((hx-hp)==0) return zero*x; x = fabsf(x); p = fabsf(p); if (hp<0x01000000) { if(x+x>p) { x-=p; if(x+x>=p) x -= p; } } else { p_half = (float)0.5*p; if(x>p_half) { x-=p; if(x>=p_half) x -= p; } } GET_FLOAT_WORD(hx,x); if ((hx&0x7fffffff)==0) hx = 0; SET_FLOAT_WORD(x,hx^sx); return x; } diff --git a/lib/msun/src/e_remainderl.c b/lib/msun/src/e_remainderl.c index 4606cf874d75..7a681cdb1289 100644 --- a/lib/msun/src/e_remainderl.c +++ b/lib/msun/src/e_remainderl.c @@ -1,38 +1,37 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include long double remainderl(long double x, long double y) { int quo; return (remquol(x, y, &quo)); } diff --git a/lib/msun/src/e_scalb.c b/lib/msun/src/e_scalb.c index 8a38ddb68d81..285ef8335913 100644 --- a/lib/msun/src/e_scalb.c +++ b/lib/msun/src/e_scalb.c @@ -1,45 +1,44 @@ /* @(#)e_scalb.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * scalb(x, fn) is provide for * passing various standard test suite. One * should use scalbn() instead. */ #include "math.h" #include "math_private.h" #ifdef _SCALB_INT double scalb(double x, int fn) #else double scalb(double x, double fn) #endif { #ifdef _SCALB_INT return scalbn(x,fn); #else if (isnan(x)||isnan(fn)) return x*fn; if (!finite(fn)) { if(fn>0.0) return x*fn; else return x/(-fn); } if (rint(fn)!=fn) return (fn-fn)/(fn-fn); if ( fn > 65000.0) return scalbn(x, 65000); if (-fn > 65000.0) return scalbn(x,-65000); return scalbn(x,(int)fn); #endif } diff --git a/lib/msun/src/e_scalbf.c b/lib/msun/src/e_scalbf.c index ca94a9fb1634..557a5a007053 100644 --- a/lib/msun/src/e_scalbf.c +++ b/lib/msun/src/e_scalbf.c @@ -1,41 +1,40 @@ /* e_scalbf.c -- float version of e_scalb.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" #ifdef _SCALB_INT float scalbf(float x, int fn) #else float scalbf(float x, float fn) #endif { #ifdef _SCALB_INT return scalbnf(x,fn); #else if ((isnanf)(x)||(isnanf)(fn)) return x*fn; if (!finitef(fn)) { if(fn>(float)0.0) return x*fn; else return x/(-fn); } if (rintf(fn)!=fn) return (fn-fn)/(fn-fn); if ( fn > (float)65000.0) return scalbnf(x, 65000); if (-fn > (float)65000.0) return scalbnf(x,-65000); return scalbnf(x,(int)fn); #endif } diff --git a/lib/msun/src/e_sinh.c b/lib/msun/src/e_sinh.c index b19a4a2f7d48..5ab2ca053b0f 100644 --- a/lib/msun/src/e_sinh.c +++ b/lib/msun/src/e_sinh.c @@ -1,77 +1,76 @@ /* @(#)e_sinh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* sinh(x) * Method : * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 * 1. Replace x by |x| (sinh(-x) = -sinh(x)). * 2. * E + E/(E+1) * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) * 2 * * 22 <= x <= lnovft : sinh(x) := exp(x)/2 * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) * ln2ovft < x : sinh(x) := x*shuge (overflow) * * Special cases: * sinh(x) is |x| if x is +INF, -INF, or NaN. * only sinh(0)=0 is exact for finite x. */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, shuge = 1.0e307; double sinh(double x) { double t,h; int32_t ix,jx; /* High word of |x|. */ GET_HIGH_WORD(jx,x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x+x; h = 0.5; 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 = expm1(fabs(x)); if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); return h*(t+t/(t+one)); } /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x40862E42) return h*exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ if (ix<=0x408633CE) return h*2.0*__ldexp_exp(fabs(x), -1); /* |x| > overflowthresold, sinh(x) overflow */ return x*shuge; } #if (LDBL_MANT_DIG == 53) __weak_reference(sinh, sinhl); #endif diff --git a/lib/msun/src/e_sinhf.c b/lib/msun/src/e_sinhf.c index 7aa177b69f11..e9fe7320d449 100644 --- a/lib/msun/src/e_sinhf.c +++ b/lib/msun/src/e_sinhf.c @@ -1,54 +1,53 @@ /* e_sinhf.c -- float version of e_sinh.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0, shuge = 1.0e37; float sinhf(float x) { float t,h; int32_t ix,jx; GET_FLOAT_WORD(jx,x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7f800000) return x+x; h = 0.5; if (jx<0) h = -h; /* |x| in [0,9], return sign(x)*0.5*(E+E/(E+1))) */ if (ix < 0x41100000) { /* |x|<9 */ if (ix<0x39800000) /* |x|<2**-12 */ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ t = expm1f(fabsf(x)); if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one)); return h*(t+t/(t+one)); } /* |x| in [9, logf(maxfloat)] return 0.5*exp(|x|) */ if (ix < 0x42b17217) return h*expf(fabsf(x)); /* |x| in [logf(maxfloat), overflowthresold] */ if (ix<=0x42b2d4fc) return h*2.0F*__ldexp_expf(fabsf(x), -1); /* |x| > overflowthresold, sinh(x) overflow */ return x*shuge; } diff --git a/lib/msun/src/e_sinhl.c b/lib/msun/src/e_sinhl.c index 121bace1d6c1..cf481b2abd96 100644 --- a/lib/msun/src/e_sinhl.c +++ b/lib/msun/src/e_sinhl.c @@ -1,132 +1,131 @@ /* from: FreeBSD: head/lib/msun/src/e_sinhl.c XXX */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See e_sinh.c for complete comments. * * Converted to long double by Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #include "k_expl.h" #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const long double shuge = 0x1p16383L; #if LDBL_MANT_DIG == 64 /* * Domain [-1, 1], range ~[-6.6749e-22, 6.6749e-22]: * |sinh(x)/x - s(x)| < 2**-70.3 */ static const union IEEEl2bits S3u = LD80C(0xaaaaaaaaaaaaaaaa, -3, 1.66666666666666666658e-1L); #define S3 S3u.e static const double S5 = 8.3333333333333332e-3, /* 0x11111111111111.0p-59 */ S7 = 1.9841269841270074e-4, /* 0x1a01a01a01a070.0p-65 */ S9 = 2.7557319223873889e-6, /* 0x171de3a5565fe6.0p-71 */ S11 = 2.5052108406704084e-8, /* 0x1ae6456857530f.0p-78 */ S13 = 1.6059042748655297e-10, /* 0x161245fa910697.0p-85 */ S15 = 7.6470006914396920e-13, /* 0x1ae7ce4eff2792.0p-93 */ S17 = 2.8346142308424267e-15; /* 0x19882ce789ffc6.0p-101 */ #elif LDBL_MANT_DIG == 113 /* * Domain [-1, 1], range ~[-2.9673e-36, 2.9673e-36]: * |sinh(x)/x - s(x)| < 2**-118.0 */ static const long double S3 = 1.66666666666666666666666666666666033e-1L, /* 0x1555555555555555555555555553b.0p-115L */ S5 = 8.33333333333333333333333333337643193e-3L, /* 0x111111111111111111111111180f5.0p-119L */ S7 = 1.98412698412698412698412697391263199e-4L, /* 0x1a01a01a01a01a01a01a0176aad11.0p-125L */ S9 = 2.75573192239858906525574406205464218e-6L, /* 0x171de3a556c7338faac243aaa9592.0p-131L */ S11 = 2.50521083854417187749675637460977997e-8L, /* 0x1ae64567f544e38fe59b3380d7413.0p-138L */ S13 = 1.60590438368216146368737762431552702e-10L, /* 0x16124613a86d098059c7620850fc2.0p-145L */ S15 = 7.64716373181980539786802470969096440e-13L, /* 0x1ae7f3e733b814193af09ce723043.0p-153L */ S17 = 2.81145725434775409870584280722701574e-15L; /* 0x1952c77030c36898c3fd0b6dfc562.0p-161L */ static const double S19= 8.2206352435411005e-18, /* 0x12f49b4662b86d.0p-109 */ S21= 1.9572943931418891e-20, /* 0x171b8f2fab9628.0p-118 */ S23 = 3.8679983530666939e-23, /* 0x17617002b73afc.0p-127 */ S25 = 6.5067867911512749e-26; /* 0x1423352626048a.0p-136 */ #else #error "Unsupported long double format" #endif /* LDBL_MANT_DIG == 64 */ /* log(2**16385 - 0.5) rounded up: */ static const float o_threshold = 1.13572168e4; /* 0xb174de.0p-10 */ long double sinhl(long double x) { long double hi,lo,x2,x4; #if LDBL_MANT_DIG == 113 double dx2; #endif double s; int16_t ix,jx; GET_LDBL_EXPSIGN(jx,x); ix = jx&0x7fff; /* x is INF or NaN */ if(ix>=0x7fff) return x+x; ENTERI(); s = 1; if (jx<0) s = -1; /* |x| < 64, return x, s(x), or accurate s*(exp(|x|)/2-1/exp(|x|)/2) */ if (ix<0x4005) { /* |x|<64 */ if (ix1) RETURNI(x); /* sinh(tiny) = tiny with inexact */ if (ix<0x3fff) { /* |x|<1 */ x2 = x*x; #if LDBL_MANT_DIG == 64 x4 = x2*x2; RETURNI(((S17*x2 + S15)*x4 + (S13*x2 + S11))*(x2*x*x4*x4) + ((S9*x2 + S7)*x2 + S5)*(x2*x*x2) + S3*(x2*x) + x); #elif LDBL_MANT_DIG == 113 dx2 = x2; RETURNI(((((((((((S25*dx2 + S23)*dx2 + S21)*x2 + S19)*x2 + S17)*x2 + S15)*x2 + S13)*x2 + S11)*x2 + S9)*x2 + S7)*x2 + S5)* (x2*x*x2) + S3*(x2*x) + x); #endif } k_hexpl(fabsl(x), &hi, &lo); RETURNI(s*(lo - 0.25/(hi + lo) + hi)); } /* |x| in [64, o_threshold], return correctly-overflowing s*exp(|x|)/2 */ if (fabsl(x) <= o_threshold) RETURNI(s*hexpl(fabsl(x))); /* |x| > o_threshold, sinh(x) overflow */ return x*shuge; } diff --git a/lib/msun/src/e_sqrt.c b/lib/msun/src/e_sqrt.c index ea588c97f5d1..e810368921bd 100644 --- a/lib/msun/src/e_sqrt.c +++ b/lib/msun/src/e_sqrt.c @@ -1,457 +1,456 @@ /* @(#)e_sqrt.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" #ifdef USE_BUILTIN_SQRT double sqrt(double x) { return (__builtin_sqrt(x)); } #else /* sqrt(x) * Return correctly rounded sqrt. * ------------------------------------------ * | Use the hardware sqrt if you have one | * ------------------------------------------ * Method: * Bit by bit method using integer arithmetic. (Slow, but portable) * 1. Normalization * Scale x to y in [1,4) with even powers of 2: * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then * sqrt(x) = 2^k * sqrt(y) * 2. Bit by bit computation * Let q = sqrt(y) truncated to i bit after binary point (q = 1), * i 0 * i+1 2 * s = 2*q , and y = 2 * ( y - q ). (1) * i i i i * * To compute q from q , one checks whether * i+1 i * * -(i+1) 2 * (q + 2 ) <= y. (2) * i * -(i+1) * If (2) is false, then q = q ; otherwise q = q + 2 . * i+1 i i+1 i * * With some algebric manipulation, it is not difficult to see * that (2) is equivalent to * -(i+1) * s + 2 <= y (3) * i i * * The advantage of (3) is that s and y can be computed by * i i * the following recurrence formula: * if (3) is false * * s = s , y = y ; (4) * i+1 i i+1 i * * otherwise, * -i -(i+1) * s = s + 2 , y = y - s - 2 (5) * i+1 i i+1 i i * * One may easily use induction to prove (4) and (5). * Note. Since the left hand side of (3) contain only i+2 bits, * it does not necessary to do a full (53-bit) comparison * in (3). * 3. Final rounding * After generating the 53 bits result, we compute one more bit. * Together with the remainder, we can decide whether the * result is exact, bigger than 1/2ulp, or less than 1/2ulp * (it will never equal to 1/2ulp). * The rounding mode can be detected by checking whether * huge + tiny is equal to huge, and whether huge - tiny is * equal to huge for some floating point number "huge" and "tiny". * * Special cases: * sqrt(+-0) = +-0 ... exact * sqrt(inf) = inf * sqrt(-ve) = NaN ... with invalid signal * sqrt(NaN) = NaN ... with invalid signal for signaling NaN * * Other methods : see the appended file at the end of the program below. *--------------- */ static const double one = 1.0, tiny=1.0e-300; double sqrt(double x) { double z; int32_t sign = (int)0x80000000; int32_t ix0,s0,q,m,t,i; u_int32_t r,t1,s1,ix1,q1; EXTRACT_WORDS(ix0,ix1,x); /* take care of Inf and NaN */ if((ix0&0x7ff00000)==0x7ff00000) { return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf sqrt(-inf)=sNaN */ } /* take care of zero */ if(ix0<=0) { if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ else if(ix0<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ } /* normalize x */ m = (ix0>>20); if(m==0) { /* subnormal x */ while(ix0==0) { m -= 21; ix0 |= (ix1>>11); ix1 <<= 21; } for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; m -= i-1; ix0 |= (ix1>>(32-i)); ix1 <<= i; } m -= 1023; /* unbias exponent */ ix0 = (ix0&0x000fffff)|0x00100000; if(m&1){ /* odd m, double x to make it even */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; } m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ r = 0x00200000; /* r = moving bit from right to left */ while(r!=0) { t = s0+r; if(t<=ix0) { s0 = t+r; ix0 -= t; q += r; } ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; r>>=1; } r = sign; while(r!=0) { t1 = s1+r; t = s0; if((t>31); ix1 += ix1; r>>=1; } /* use floating add to find out rounding direction */ if((ix0|ix1)!=0) { z = one-tiny; /* trigger inexact flag */ if (z>=one) { z = one+tiny; if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} else if (z>one) { if (q1==(u_int32_t)0xfffffffe) q+=1; q1+=2; } else q1 += (q1&1); } } ix0 = (q>>1)+0x3fe00000; ix1 = q1>>1; if ((q&1)==1) ix1 |= sign; ix0 += (m <<20); INSERT_WORDS(z,ix0,ix1); return z; } #endif #if (LDBL_MANT_DIG == 53) __weak_reference(sqrt, sqrtl); #endif /* Other methods (use floating-point arithmetic) ------------- (This is a copy of a drafted paper by Prof W. Kahan and K.C. Ng, written in May, 1986) Two algorithms are given here to implement sqrt(x) (IEEE double precision arithmetic) in software. Both supply sqrt(x) correctly rounded. The first algorithm (in Section A) uses newton iterations and involves four divisions. The second one uses reciproot iterations to avoid division, but requires more multiplications. Both algorithms need the ability to chop results of arithmetic operations instead of round them, and the INEXACT flag to indicate when an arithmetic operation is executed exactly with no roundoff error, all part of the standard (IEEE 754-1985). The ability to perform shift, add, subtract and logical AND operations upon 32-bit words is needed too, though not part of the standard. A. sqrt(x) by Newton Iteration (1) Initial approximation Let x0 and x1 be the leading and the trailing 32-bit words of a floating point number x (in IEEE double format) respectively 1 11 52 ...widths ------------------------------------------------------ x: |s| e | f | ------------------------------------------------------ msb lsb msb lsb ...order ------------------------ ------------------------ x0: |s| e | f1 | x1: | f2 | ------------------------ ------------------------ By performing shifts and subtracts on x0 and x1 (both regarded as integers), we obtain an 8-bit approximation of sqrt(x) as follows. k := (x0>>1) + 0x1ff80000; y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits Here k is a 32-bit integer and T1[] is an integer array containing correction terms. Now magically the floating value of y (y's leading 32-bit word is y0, the value of its trailing word is 0) approximates sqrt(x) to almost 8-bit. Value of T1: static int T1[32]= { 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; (2) Iterative refinement Apply Heron's rule three times to y, we have y approximates sqrt(x) to within 1 ulp (Unit in the Last Place): y := (y+x/y)/2 ... almost 17 sig. bits y := (y+x/y)/2 ... almost 35 sig. bits y := y-(y-x/y)/2 ... within 1 ulp Remark 1. Another way to improve y to within 1 ulp is: y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) 2 (x-y )*y y := y + 2* ---------- ...within 1 ulp 2 3y + x This formula has one division fewer than the one above; however, it requires more multiplications and additions. Also x must be scaled in advance to avoid spurious overflow in evaluating the expression 3y*y+x. Hence it is not recommended uless division is slow. If division is very slow, then one should use the reciproot algorithm given in section B. (3) Final adjustment By twiddling y's last bit it is possible to force y to be correctly rounded according to the prevailing rounding mode as follows. Let r and i be copies of the rounding mode and inexact flag before entering the square root program. Also we use the expression y+-ulp for the next representable floating numbers (up and down) of y. Note that y+-ulp = either fixed point y+-1, or multiply y by nextafter(1,+-inf) in chopped mode. I := FALSE; ... reset INEXACT flag I R := RZ; ... set rounding mode to round-toward-zero z := x/y; ... chopped quotient, possibly inexact If(not I) then { ... if the quotient is exact if(z=y) { I := i; ... restore inexact flag R := r; ... restore rounded mode return sqrt(x):=y. } else { z := z - ulp; ... special rounding } } i := TRUE; ... sqrt(x) is inexact If (r=RN) then z=z+ulp ... rounded-to-nearest If (r=RP) then { ... round-toward-+inf y = y+ulp; z=z+ulp; } y := y+z; ... chopped sum y0:=y0-0x00100000; ... y := y/2 is correctly rounded. I := i; ... restore inexact flag R := r; ... restore rounded mode return sqrt(x):=y. (4) Special cases Square root of +inf, +-0, or NaN is itself; Square root of a negative number is NaN with invalid signal. B. sqrt(x) by Reciproot Iteration (1) Initial approximation Let x0 and x1 be the leading and the trailing 32-bit words of a floating point number x (in IEEE double format) respectively (see section A). By performing shifs and subtracts on x0 and y0, we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. k := 0x5fe80000 - (x0>>1); y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits Here k is a 32-bit integer and T2[] is an integer array containing correction terms. Now magically the floating value of y (y's leading 32-bit word is y0, the value of its trailing word y1 is set to zero) approximates 1/sqrt(x) to almost 7.8-bit. Value of T2: static int T2[64]= { 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; (2) Iterative refinement Apply Reciproot iteration three times to y and multiply the result by x to get an approximation z that matches sqrt(x) to about 1 ulp. To be exact, we will have -1ulp < sqrt(x)-z<1.0625ulp. ... set rounding mode to Round-to-nearest y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) ... special arrangement for better accuracy z := x*y ... 29 bits to sqrt(x), with z*y<1 z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that (a) the term z*y in the final iteration is always less than 1; (b) the error in the final result is biased upward so that -1 ulp < sqrt(x) - z < 1.0625 ulp instead of |sqrt(x)-z|<1.03125ulp. (3) Final adjustment By twiddling y's last bit it is possible to force y to be correctly rounded according to the prevailing rounding mode as follows. Let r and i be copies of the rounding mode and inexact flag before entering the square root program. Also we use the expression y+-ulp for the next representable floating numbers (up and down) of y. Note that y+-ulp = either fixed point y+-1, or multiply y by nextafter(1,+-inf) in chopped mode. R := RZ; ... set rounding mode to round-toward-zero switch(r) { case RN: ... round-to-nearest if(x<= z*(z-ulp)...chopped) z = z - ulp; else if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; break; case RZ:case RM: ... round-to-zero or round-to--inf R:=RP; ... reset rounding mod to round-to-+inf if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; break; case RP: ... round-to-+inf if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else if(x>z*z ...chopped) z = z+ulp; break; } Remark 3. The above comparisons can be done in fixed point. For example, to compare x and w=z*z chopped, it suffices to compare x1 and w1 (the trailing parts of x and w), regarding them as two's complement integers. ...Is z an exact square root? To determine whether z is an exact square root of x, let z1 be the trailing part of z, and also let x0 and x1 be the leading and trailing parts of x. If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 I := 1; ... Raise Inexact flag: z is not exact else { j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 k := z1 >> 26; ... get z's 25-th and 26-th fraction bits I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); } R:= r ... restore rounded mode return sqrt(x):=z. If multiplication is cheaper then the foregoing red tape, the Inexact flag can be evaluated by I := i; I := (z*z!=x) or I. Note that z*z can overwrite I; this value must be sensed if it is True. Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be zero. -------------------- z1: | f2 | -------------------- bit 31 bit 0 Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd or even of logb(x) have the following relations: ------------------------------------------------- bit 27,26 of z1 bit 1,0 of x1 logb(x) ------------------------------------------------- 00 00 odd and even 01 01 even 10 10 odd 10 00 even 11 01 even ------------------------------------------------- (4) Special cases (see (4) of Section A). */ diff --git a/lib/msun/src/e_sqrtl.c b/lib/msun/src/e_sqrtl.c index beb4e7a9c948..a785536ea7e2 100644 --- a/lib/msun/src/e_sqrtl.c +++ b/lib/msun/src/e_sqrtl.c @@ -1,159 +1,158 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #include "math.h" /* Return (x + ulp) for normal positive x. Assumes no overflow. */ static inline long double inc(long double x) { union IEEEl2bits u; u.e = x; if (++u.bits.manl == 0) { if (++u.bits.manh == 0) { u.bits.exp++; u.bits.manh |= LDBL_NBIT; } } return (u.e); } /* Return (x - ulp) for normal positive x. Assumes no underflow. */ static inline long double dec(long double x) { union IEEEl2bits u; u.e = x; if (u.bits.manl-- == 0) { if (u.bits.manh-- == LDBL_NBIT) { u.bits.exp--; u.bits.manh |= LDBL_NBIT; } } return (u.e); } #pragma STDC FENV_ACCESS ON /* * This is slow, but simple and portable. You should use hardware sqrt * if possible. */ long double sqrtl(long double x) { union IEEEl2bits u; int k, r; long double lo, xn; fenv_t env; u.e = x; /* If x = NaN, then sqrt(x) = NaN. */ /* If x = Inf, then sqrt(x) = Inf. */ /* If x = -Inf, then sqrt(x) = NaN. */ if (u.bits.exp == LDBL_MAX_EXP * 2 - 1) return (x * x + x); /* If x = +-0, then sqrt(x) = +-0. */ if ((u.bits.manh | u.bits.manl | u.bits.exp) == 0) return (x); /* If x < 0, then raise invalid and return NaN */ if (u.bits.sign) return ((x - x) / (x - x)); feholdexcept(&env); if (u.bits.exp == 0) { /* Adjust subnormal numbers. */ u.e *= 0x1.0p514; k = -514; } else { k = 0; } /* * u.e is a normal number, so break it into u.e = e*2^n where * u.e = (2*e)*2^2k for odd n and u.e = (4*e)*2^2k for even n. */ if ((u.bits.exp - 0x3ffe) & 1) { /* n is odd. */ k += u.bits.exp - 0x3fff; /* 2k = n - 1. */ u.bits.exp = 0x3fff; /* u.e in [1,2). */ } else { k += u.bits.exp - 0x4000; /* 2k = n - 2. */ u.bits.exp = 0x4000; /* u.e in [2,4). */ } /* * Newton's iteration. * Split u.e into a high and low part to achieve additional precision. */ xn = sqrt(u.e); /* 53-bit estimate of sqrtl(x). */ #if LDBL_MANT_DIG > 100 xn = (xn + (u.e / xn)) * 0.5; /* 106-bit estimate. */ #endif lo = u.e; u.bits.manl = 0; /* Zero out lower bits. */ lo = (lo - u.e) / xn; /* Low bits divided by xn. */ xn = xn + (u.e / xn); /* High portion of estimate. */ u.e = xn + lo; /* Combine everything. */ u.bits.exp += (k >> 1) - 1; feclearexcept(FE_INEXACT); r = fegetround(); fesetround(FE_TOWARDZERO); /* Set to round-toward-zero. */ xn = x / u.e; /* Chopped quotient (inexact?). */ if (!fetestexcept(FE_INEXACT)) { /* Quotient is exact. */ if (xn == u.e) { fesetenv(&env); return (u.e); } /* Round correctly for inputs like x = y**2 - ulp. */ xn = dec(xn); /* xn = xn - ulp. */ } if (r == FE_TONEAREST) { xn = inc(xn); /* xn = xn + ulp. */ } else if (r == FE_UPWARD) { u.e = inc(u.e); /* u.e = u.e + ulp. */ xn = inc(xn); /* xn = xn + ulp. */ } u.e = u.e + xn; /* Chopped sum. */ feupdateenv(&env); /* Restore env and raise inexact */ u.bits.exp--; return (u.e); } diff --git a/lib/msun/src/k_cos.c b/lib/msun/src/k_cos.c index 8cc9a0e83efe..1035672c9b75 100644 --- a/lib/msun/src/k_cos.c +++ b/lib/msun/src/k_cos.c @@ -1,77 +1,76 @@ /* @(#)k_cos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * __kernel_cos( x, y ) * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * * Algorithm * 1. Since cos(-x) = cos(x), we need only to consider positive x. * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. * 3. cos(x) is approximated by a polynomial of degree 14 on * [0,pi/4] * 4 14 * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x * where the remez error is * * | 2 4 6 8 10 12 14 | -58 * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 * | | * * 4 6 8 10 12 14 * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then * cos(x) ~ 1 - x*x/2 + r * since cos(x+y) ~ cos(x) - sin(x)*y * ~ cos(x) - x*y, * a correction term is necessary in cos(x) and hence * cos(x+y) = 1 - (x*x/2 - (r - x*y)) * For better accuracy, rearrange to * cos(x+y) ~ w + (tmp + (r-x*y)) * where w = 1 - x*x/2 and tmp is a tiny correction term * (1 - x*x/2 == w + tmp exactly in infinite precision). * The exactness of w + tmp in infinite precision depends on w * and tmp having the same precision as x. If they have extra * precision due to compiler bugs, then the extra precision is * only good provided it is retained in all terms of the final * expression for cos(). Retention happens in all cases tested * under FreeBSD, so don't pessimize things by forcibly clipping * any extra precision in w. */ #include "math.h" #include "math_private.h" static const double one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ double __kernel_cos(double x, double y) { double hz,z,r,w; z = x*x; w = z*z; r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); hz = 0.5*z; w = one-hz; return w + (((one-w)-hz) + (z*r-x*y)); } diff --git a/lib/msun/src/k_cosf.c b/lib/msun/src/k_cosf.c index a93011b52c0d..934c1c7a785e 100644 --- a/lib/msun/src/k_cosf.c +++ b/lib/msun/src/k_cosf.c @@ -1,45 +1,41 @@ /* k_cosf.c -- float version of k_cos.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Debugged and optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#ifndef INLINE_KERNEL_COSDF -#include -#endif - #include "math.h" #include "math_private.h" /* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ static const double one = 1.0, C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */ C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */ C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */ C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ #ifdef INLINE_KERNEL_COSDF static __inline #endif float __kernel_cosdf(double x) { double r, w, z; /* Try to optimize for parallel evaluation as in k_tanf.c. */ z = x*x; w = z*z; r = C2+z*C3; return ((one+z*C0) + w*C1) + (w*z)*r; } diff --git a/lib/msun/src/k_exp.c b/lib/msun/src/k_exp.c index ce8e3591827a..383616d64d55 100644 --- a/lib/msun/src/k_exp.c +++ b/lib/msun/src/k_exp.c @@ -1,109 +1,108 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" static const uint32_t k = 1799; /* constant for reduction */ static const double kln2 = 1246.97177782734161156; /* k * ln2 */ /* * Compute exp(x), scaled to avoid spurious overflow. An exponent is * returned separately in 'expt'. * * Input: ln(DBL_MAX) <= x < ln(2 * DBL_MAX / DBL_MIN_DENORM) ~= 1454.91 * Output: 2**1023 <= y < 2**1024 */ static double __frexp_exp(double x, int *expt) { double exp_x; uint32_t hx; /* * We use exp(x) = exp(x - kln2) * 2**k, carefully chosen to * minimize |exp(kln2) - 2**k|. We also scale the exponent of * exp_x to MAX_EXP so that the result can be multiplied by * a tiny number without losing accuracy due to denormalization. */ exp_x = exp(x - kln2); GET_HIGH_WORD(hx, exp_x); *expt = (hx >> 20) - (0x3ff + 1023) + k; SET_HIGH_WORD(exp_x, (hx & 0xfffff) | ((0x3ff + 1023) << 20)); return (exp_x); } /* * __ldexp_exp(x, expt) and __ldexp_cexp(x, expt) compute exp(x) * 2**expt. * They are intended for large arguments (real part >= ln(DBL_MAX)) * where care is needed to avoid overflow. * * The present implementation is narrowly tailored for our hyperbolic and * exponential functions. We assume expt is small (0 or -1), and the caller * has filtered out very large x, for which overflow would be inevitable. */ double __ldexp_exp(double x, int expt) { double exp_x, scale; int ex_expt; exp_x = __frexp_exp(x, &ex_expt); expt += ex_expt; INSERT_WORDS(scale, (0x3ff + expt) << 20, 0); return (exp_x * scale); } double complex __ldexp_cexp(double complex z, int expt) { double c, exp_x, s, scale1, scale2, x, y; int ex_expt, half_expt; x = creal(z); y = cimag(z); exp_x = __frexp_exp(x, &ex_expt); expt += ex_expt; /* * Arrange so that scale1 * scale2 == 2**expt. We use this to * compensate for scalbn being horrendously slow. */ half_expt = expt / 2; INSERT_WORDS(scale1, (0x3ff + half_expt) << 20, 0); half_expt = expt - half_expt; INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0); sincos(y, &s, &c); return (CMPLX(c * exp_x * scale1 * scale2, s * exp_x * scale1 * scale2)); } diff --git a/lib/msun/src/k_expf.c b/lib/msun/src/k_expf.c index 61478214e736..2af0c6dd3543 100644 --- a/lib/msun/src/k_expf.c +++ b/lib/msun/src/k_expf.c @@ -1,88 +1,87 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" static const uint32_t k = 235; /* constant for reduction */ static const float kln2 = 162.88958740F; /* k * ln2 */ /* * See k_exp.c for details. * * Input: ln(FLT_MAX) <= x < ln(2 * FLT_MAX / FLT_MIN_DENORM) ~= 192.7 * Output: 2**127 <= y < 2**128 */ static float __frexp_expf(float x, int *expt) { float exp_x; uint32_t hx; exp_x = expf(x - kln2); GET_FLOAT_WORD(hx, exp_x); *expt = (hx >> 23) - (0x7f + 127) + k; SET_FLOAT_WORD(exp_x, (hx & 0x7fffff) | ((0x7f + 127) << 23)); return (exp_x); } float __ldexp_expf(float x, int expt) { float exp_x, scale; int ex_expt; exp_x = __frexp_expf(x, &ex_expt); expt += ex_expt; SET_FLOAT_WORD(scale, (0x7f + expt) << 23); return (exp_x * scale); } float complex __ldexp_cexpf(float complex z, int expt) { float c, exp_x, s, scale1, scale2, x, y; int ex_expt, half_expt; x = crealf(z); y = cimagf(z); exp_x = __frexp_expf(x, &ex_expt); expt += ex_expt; half_expt = expt / 2; SET_FLOAT_WORD(scale1, (0x7f + half_expt) << 23); half_expt = expt - half_expt; SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23); sincosf(y, &s, &c); return (CMPLXF(c * exp_x * scale1 * scale2, s * exp_x * scale1 * scale2)); } diff --git a/lib/msun/src/k_log.h b/lib/msun/src/k_log.h index f15227139324..e4fb2d4cab62 100644 --- a/lib/msun/src/k_log.h +++ b/lib/msun/src/k_log.h @@ -1,98 +1,97 @@ /* @(#)e_log.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * k_log1p(f): * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)]. * * The following describes the overall strategy for computing * logarithms in base e. The argument reduction and adding the final * term of the polynomial are done by the caller for increased accuracy * when different bases are used. * * Method : * 1. Argument Reduction: find k and f such that * x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * 2. Approximation of log(1+f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Reme algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s * (the values of Lg1 to Lg7 are listed in the program) * and * | 2 14 | -58.45 * | Lg1*s +...+Lg7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log(1+f) = f - s*(f - R) (if f is not too large) * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) * * 3. Finally, log(x) = k*ln2 + log(1+f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log(x) is NaN with signal if x < 0 (including -INF) ; * log(+INF) is +INF; log(0) is -INF with signal; * log(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ static const double Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ /* * We always inline k_log1p(), since doing so produces a * substantial performance improvement (~40% on amd64). */ static inline double k_log1p(double f) { double hfsq,s,z,R,w,t1,t2; s = f/(2.0+f); z = s*s; w = z*z; t1= w*(Lg2+w*(Lg4+w*Lg6)); t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); R = t2+t1; hfsq=0.5*f*f; return s*(hfsq+R); } diff --git a/lib/msun/src/k_logf.h b/lib/msun/src/k_logf.h index 3f637cd6a9ec..72b675143d26 100644 --- a/lib/msun/src/k_logf.h +++ b/lib/msun/src/k_logf.h @@ -1,37 +1,36 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * Float version of k_log.h. See the latter for most comments. */ static const float /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ static inline float k_log1pf(float f) { float hfsq,s,z,R,w,t1,t2; s = f/((float)2.0+f); z = s*s; w = z*z; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); R = t2+t1; hfsq=(float)0.5*f*f; return s*(hfsq+R); } diff --git a/lib/msun/src/k_rem_pio2.c b/lib/msun/src/k_rem_pio2.c index 952bebb6ed2d..a8703596b42b 100644 --- a/lib/msun/src/k_rem_pio2.c +++ b/lib/msun/src/k_rem_pio2.c @@ -1,441 +1,440 @@ /* @(#)k_rem_pio2.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * __kernel_rem_pio2(x,y,e0,nx,prec) * double x[],y[]; int e0,nx,prec; * * __kernel_rem_pio2 return the last three digits of N with * y = x - N*pi/2 * so that |y| < pi/2. * * The method is to compute the integer (mod 8) and fraction parts of * (2/pi)*x without doing the full multiplication. In general we * skip the part of the product that are known to be a huge integer ( * more accurately, = 0 mod 8 ). Thus the number of operations are * independent of the exponent of the input. * * (2/pi) is represented by an array of 24-bit integers in ipio2[]. * * Input parameters: * x[] The input value (must be positive) is broken into nx * pieces of 24-bit integers in double precision format. * x[i] will be the i-th 24 bit of x. The scaled exponent * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 * match x's up to 24 bits. * * Example of breaking a double positive z into x[0]+x[1]+x[2]: * e0 = ilogb(z)-23 * z = scalbn(z,-e0) * for i = 0,1,2 * x[i] = floor(z) * z = (z-x[i])*2**24 * * * y[] output result in an array of double precision numbers. * The dimension of y[] is: * 24-bit precision 1 * 53-bit precision 2 * 64-bit precision 2 * 113-bit precision 3 * The actual value is the sum of them. Thus for 113-bit * precision, one may have to do something like: * * long double t,w,r_head, r_tail; * t = (long double)y[2] + (long double)y[1]; * w = (long double)y[0]; * r_head = t+w; * r_tail = w - (r_head - t); * * e0 The exponent of x[0]. Must be <= 16360 or you need to * expand the ipio2 table. * * nx dimension of x[] * * prec an integer indicating the precision: * 0 24 bits (single) * 1 53 bits (double) * 2 64 bits (extended) * 3 113 bits (quad) * * External function: * double scalbn(), floor(); * * * Here is the description of some local variables: * * jk jk+1 is the initial number of terms of ipio2[] needed * in the computation. The minimum and recommended value * for jk is 3,4,4,6 for single, double, extended, and quad. * jk+1 must be 2 larger than you might expect so that our * recomputation test works. (Up to 24 bits in the integer * part (the 24 bits of it that we compute) and 23 bits in * the fraction part may be lost to cancellation before we * recompute.) * * jz local integer variable indicating the number of * terms of ipio2[] used. * * jx nx - 1 * * jv index for pointing to the suitable ipio2[] for the * computation. In general, we want * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 * is an integer. Thus * e0-3-24*jv >= 0 or (e0-3)/24 >= jv * Hence jv = max(0,(e0-3)/24). * * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. * * q[] double array with integral value, representing the * 24-bits chunk of the product of x and 2/pi. * * q0 the corresponding exponent of q[0]. Note that the * exponent for q[i] would be q0-24*i. * * PIo2[] double precision array, obtained by cutting pi/2 * into 24 bits chunks. * * f[] ipio2[] in floating point * * iq[] integer array by breaking up q[] in 24-bits chunk. * * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] * * ih integer. If >0 it indicates q[] is >= 0.5, hence * it also indicates the *sign* of the result. * */ /* * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ /* * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi * * integer array, contains the (24*i)-th to (24*i+23)-th * bit of 2/pi after binary point. The corresponding * floating value is * * ipio2[i] * 2^(-24(i+1)). * * NB: This table must have at least (e0-3)/24 + jk terms. * For quad precision (e0 <= 16360, jk = 6), this is 686. */ static const int32_t ipio2[] = { 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, #if LDBL_MAX_EXP > 1024 #if LDBL_MAX_EXP > 16384 #error "ipio2 table needs to be expanded" #endif 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, 0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, 0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, 0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, 0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, 0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, 0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, 0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, 0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, 0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, 0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, 0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, 0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, 0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, 0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, 0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, 0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, 0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, 0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, 0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, 0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, 0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, 0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, 0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, 0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, 0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, 0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, 0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, 0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, 0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, 0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, 0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, 0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, 0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, 0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, 0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, 0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, 0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, 0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, 0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, 0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, 0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, 0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, 0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, 0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, 0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, 0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, 0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, 0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, 0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, 0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, 0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, 0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, 0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, 0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, 0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, 0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, 0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, 0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, 0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, 0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, 0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, 0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, 0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, 0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, 0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, 0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, 0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, 0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, 0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, #endif }; static const double PIo2[] = { 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ }; static const double zero = 0.0, one = 1.0, two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec) { int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; double z,fw,f[20],fq[20],q[20]; /* initialize jk*/ jk = init_jk[prec]; jp = jk; /* determine jx,jv,q0, note that 3>q0 */ jx = nx-1; jv = (e0-3)/24; if(jv<0) jv=0; q0 = e0-24*(jv+1); /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ j = jv-jx; m = jx+jk; for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; /* compute q[0],q[1],...q[jk] */ for (i=0;i<=jk;i++) { for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz = jk; recompute: /* distill q[] into iq[] reversingly */ for(i=0,j=jz,z=q[jz];j>0;i++,j--) { fw = (double)((int32_t)(twon24* z)); iq[i] = (int32_t)(z-two24*fw); z = q[j-1]+fw; } /* compute n */ z = scalbn(z,q0); /* actual value of z */ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ n = (int32_t) z; z -= (double)n; ih = 0; if(q0>0) { /* need iq[jz-1] to determine n */ i = (iq[jz-1]>>(24-q0)); n += i; iq[jz-1] -= i<<(24-q0); ih = iq[jz-1]>>(23-q0); } else if(q0==0) ih = iq[jz-1]>>23; else if(z>=0.5) ih=2; if(ih>0) { /* q > 0.5 */ n += 1; carry = 0; for(i=0;i0) { /* rare case: chance is 1 in 12 */ switch(q0) { case 1: iq[jz-1] &= 0x7fffff; break; case 2: iq[jz-1] &= 0x3fffff; break; } } if(ih==2) { z = one - z; if(carry!=0) z -= scalbn(one,q0); } } /* check if recomputation is needed */ if(z==zero) { j = 0; for (i=jz-1;i>=jk;i--) j |= iq[i]; if(j==0) { /* need recomputation */ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ f[jx+i] = (double) ipio2[jv+i]; for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz += k; goto recompute; } } /* chop off zero terms */ if(z==0.0) { jz -= 1; q0 -= 24; while(iq[jz]==0) { jz--; q0-=24;} } else { /* break z into 24-bit if necessary */ z = scalbn(z,-q0); if(z>=two24) { fw = (double)((int32_t)(twon24*z)); iq[jz] = (int32_t)(z-two24*fw); jz += 1; q0 += 24; iq[jz] = (int32_t) fw; } else iq[jz] = (int32_t) z ; } /* convert integer "bit" chunk to floating-point value */ fw = scalbn(one,q0); for(i=jz;i>=0;i--) { q[i] = fw*(double)iq[i]; fw*=twon24; } /* compute PIo2[0,...,jp]*q[jz,...,0] */ for(i=jz;i>=0;i--) { for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; fq[jz-i] = fw; } /* compress fq[] into y[] */ switch(prec) { case 0: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; y[0] = (ih==0)? fw: -fw; break; case 1: case 2: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; STRICT_ASSIGN(double,fw,fw); y[0] = (ih==0)? fw: -fw; fw = fq[0]-fw; for (i=1;i<=jz;i++) fw += fq[i]; y[1] = (ih==0)? fw: -fw; break; case 3: /* painful */ for (i=jz;i>0;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (i=jz;i>1;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; if(ih==0) { y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; } else { y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; } } return n&7; } diff --git a/lib/msun/src/k_sin.c b/lib/msun/src/k_sin.c index 6d24a0f21d92..4064b4c589fd 100644 --- a/lib/msun/src/k_sin.c +++ b/lib/msun/src/k_sin.c @@ -1,68 +1,67 @@ /* @(#)k_sin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* __kernel_sin( x, y, iy) * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). * * Algorithm * 1. Since sin(-x) = -sin(x), we need only to consider positive x. * 2. Callers must return sin(-0) = -0 without calling here since our * odd polynomial is not evaluated in a way that preserves -0. * Callers may do the optimization sin(x) ~ x for tiny x. * 3. sin(x) is approximated by a polynomial of degree 13 on * [0,pi/4] * 3 13 * sin(x) ~ x + S1*x + ... + S6*x * where * * |sin(x) 2 4 6 8 10 12 | -58 * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 * | x | * * 4. sin(x+y) = sin(x) + sin'(x')*y * ~ sin(x) + (1-x*x/2)*y * For better accuracy, let * 3 2 2 2 2 * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) * then 3 2 * sin(x) = x + (S1*x + (x *(r-y/2)+y)) */ #include "math.h" #include "math_private.h" static const double half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ double __kernel_sin(double x, double y, int iy) { double z,r,v,w; z = x*x; w = z*z; r = S2+z*(S3+z*S4) + z*w*(S5+z*S6); v = z*x; if(iy==0) return x+v*(S1+z*r); else return x-((z*(half*y-v*r)-y)-v*S1); } diff --git a/lib/msun/src/k_sincos.h b/lib/msun/src/k_sincos.h index a29a57c06342..796e72af89e5 100644 --- a/lib/msun/src/k_sincos.h +++ b/lib/msun/src/k_sincos.h @@ -1,50 +1,49 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * k_sin.c and k_cos.c merged by Steven G. Kargl. */ -#include static const double S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ static const double C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ static inline void __kernel_sincos(double x, double y, int iy, double *sn, double *cs) { double hz, r, v, w, z; z = x * x; w = z * z; r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6); v = z * x; if (iy == 0) *sn = x + v * (S1 + z * r); else *sn = x - ((z * (y / 2 - v * r) - y) - v * S1); r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6)); hz = z / 2; w = 1 - hz; *cs = w + (((1 - w) - hz) + (z * r - x * y)); } diff --git a/lib/msun/src/k_sincosf.h b/lib/msun/src/k_sincosf.h index 01f5d48b23ee..f031016b79d0 100644 --- a/lib/msun/src/k_sincosf.h +++ b/lib/msun/src/k_sincosf.h @@ -1,41 +1,40 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * k_sinf.c and k_cosf.c merged by Steven G. Kargl. */ -#include /* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */ static const double S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */ S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */ S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */ S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */ /* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ static const double C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */ C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */ C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */ C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ static inline void __kernel_sincosdf(double x, float *sn, float *cs) { double r, s, w, z; z = x * x; w = z * z; r = S3 + z * S4; s = z * x; *sn = (x + s * (S1 + z * S2)) + s * w * r; r = C2 + z * C3; *cs = ((1 + z * C0) + w * C1) + (w * z) * r; } diff --git a/lib/msun/src/k_sincosl.h b/lib/msun/src/k_sincosl.h index 918d49f54f54..cf8536c8e27e 100644 --- a/lib/msun/src/k_sincosl.h +++ b/lib/msun/src/k_sincosl.h @@ -1,135 +1,134 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * k_sinl.c and k_cosl.c merged by Steven G. Kargl */ -#include #if LDBL_MANT_DIG == 64 /* ld80 version of k_sincosl.c. */ #if defined(__amd64__) || defined(__i386__) /* Long double constants are slow on these arches, and broken on i386. */ static const volatile double C1hi = 0.041666666666666664, /* 0x15555555555555.0p-57 */ C1lo = 2.2598839032744733e-18, /* 0x14d80000000000.0p-111 */ S1hi = -0.16666666666666666, /* -0x15555555555555.0p-55 */ S1lo = -9.2563760475949941e-18; /* -0x15580000000000.0p-109 */ #define S1 ((long double)S1hi + S1lo) #define C1 ((long double)C1hi + C1lo) #else static const long double C1 = 0.0416666666666666666136L, /* 0xaaaaaaaaaaaaaa9b.0p-68 */ S1 = -0.166666666666666666671L; /* -0xaaaaaaaaaaaaaaab.0p-66 */ #endif static const double C2 = -0.0013888888888888874, /* -0x16c16c16c16c10.0p-62 */ C3 = 0.000024801587301571716, /* 0x1a01a01a018e22.0p-68 */ C4 = -0.00000027557319215507120, /* -0x127e4fb7602f22.0p-74 */ C5 = 0.0000000020876754400407278, /* 0x11eed8caaeccf1.0p-81 */ C6 = -1.1470297442401303e-11, /* -0x19393412bd1529.0p-89 */ C7 = 4.7383039476436467e-14, /* 0x1aac9d9af5c43e.0p-97 */ S2 = 0.0083333333333333332, /* 0x11111111111111.0p-59 */ S3 = -0.00019841269841269427, /* -0x1a01a01a019f81.0p-65 */ S4 = 0.0000027557319223597490, /* 0x171de3a55560f7.0p-71 */ S5 = -0.000000025052108218074604, /* -0x1ae64564f16cad.0p-78 */ S6 = 1.6059006598854211e-10, /* 0x161242b90243b5.0p-85 */ S7 = -7.6429779983024564e-13, /* -0x1ae42ebd1b2e00.0p-93 */ S8 = 2.6174587166648325e-15; /* 0x179372ea0b3f64.0p-101 */ static inline void __kernel_sincosl(long double x, long double y, int iy, long double *sn, long double *cs) { long double hz, r, v, w, z; z = x * x; v = z * x; /* * XXX Replace Horner scheme with an algorithm suitable for CPUs * with more complex pipelines. */ r = S2 + z * (S3 + z * (S4 + z * (S5 + z * (S6 + z * (S7 + z * S8))))); if (iy == 0) *sn = x + v * (S1 + z * r); else *sn = x - ((z * (y / 2 - v * r) - y) - v * S1); hz = z / 2; w = 1 - hz; r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * (C6 + z * C7)))))); *cs = w + (((1 - w) - hz) + (z * r - x * y)); } #elif LDBL_MANT_DIG == 113 /* ld128 version of k_sincosl.c. */ static const long double S1 = -0.16666666666666666666666666666666666606732416116558L, S2 = 0.0083333333333333333333333333333331135404851288270047L, S3 = -0.00019841269841269841269841269839935785325638310428717L, S4 = 0.27557319223985890652557316053039946268333231205686e-5L, S5 = -0.25052108385441718775048214826384312253862930064745e-7L, S6 = 0.16059043836821614596571832194524392581082444805729e-9L, S7 = -0.76471637318198151807063387954939213287488216303768e-12L, S8 = 0.28114572543451292625024967174638477283187397621303e-14L; static const double S9 = -0.82206352458348947812512122163446202498005154296863e-17, S10 = 0.19572940011906109418080609928334380560135358385256e-19, S11 = -0.38680813379701966970673724299207480965452616911420e-22, S12 = 0.64038150078671872796678569586315881020659912139412e-25; static const long double C1 = 4.16666666666666666666666666666666667e-02L, C2 = -1.38888888888888888888888888888888834e-03L, C3 = 2.48015873015873015873015873015446795e-05L, C4 = -2.75573192239858906525573190949988493e-07L, C5 = 2.08767569878680989792098886701451072e-09L, C6 = -1.14707455977297247136657111139971865e-11L, C7 = 4.77947733238738518870113294139830239e-14L, C8 = -1.56192069685858079920640872925306403e-16L, C9 = 4.11031762320473354032038893429515732e-19L, C10= -8.89679121027589608738005163931958096e-22L, C11= 1.61171797801314301767074036661901531e-24L, C12= -2.46748624357670948912574279501044295e-27L; static inline void __kernel_sincosl(long double x, long double y, int iy, long double *sn, long double *cs) { long double hz, r, v, w, z; z = x * x; v = z * x; /* * XXX Replace Horner scheme with an algorithm suitable for CPUs * with more complex pipelines. */ r = S2 + z * (S3 + z * (S4 + z * (S5 + z * (S6 + z * (S7 + z * (S8 + z * (S9 + z * (S10 + z * (S11 + z * S12))))))))); if (iy == 0) *sn = x + v * (S1 + z * r); else *sn = x - ((z * (y / 2 - v * r) - y) - v * S1); hz = z / 2; w = 1 - hz; r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * (C6 + z * (C7 + z * (C8 + z * (C9 + z * (C10 + z * (C11+z*C12))))))))))); *cs = w + (((1 - w) - hz) + (z * r - x * y)); } #else #error "Unsupported long double format" #endif diff --git a/lib/msun/src/k_sinf.c b/lib/msun/src/k_sinf.c index ef547e36bf50..ebebd9663b10 100644 --- a/lib/msun/src/k_sinf.c +++ b/lib/msun/src/k_sinf.c @@ -1,45 +1,41 @@ /* k_sinf.c -- float version of k_sin.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#ifndef INLINE_KERNEL_SINDF -#include -#endif - #include "math.h" #include "math_private.h" /* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */ static const double S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */ S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */ S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */ S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */ #ifdef INLINE_KERNEL_SINDF static __inline #endif float __kernel_sindf(double x) { double r, s, w, z; /* Try to optimize for parallel evaluation as in k_tanf.c. */ z = x*x; w = z*z; r = S3+z*S4; s = z*x; return (x + s*(S1+z*S2)) + s*w*r; } diff --git a/lib/msun/src/k_tan.c b/lib/msun/src/k_tan.c index 5ebcddda09e6..8b3e0f9124f9 100644 --- a/lib/msun/src/k_tan.c +++ b/lib/msun/src/k_tan.c @@ -1,130 +1,128 @@ /* @(#)k_tan.c 1.5 04/04/22 SMI */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -/* INDENT OFF */ -#include /* __kernel_tan( x, y, k ) * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned. * * Algorithm * 1. Since tan(-x) = -tan(x), we need only to consider positive x. * 2. Callers must return tan(-0) = -0 without calling here since our * odd polynomial is not evaluated in a way that preserves -0. * Callers may do the optimization tan(x) ~ x for tiny x. * 3. tan(x) is approximated by a odd polynomial of degree 27 on * [0,0.67434] * 3 27 * tan(x) ~ x + T1*x + ... + T13*x * where * * |tan(x) 2 4 26 | -59.2 * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 * | x | * * Note: tan(x+y) = tan(x) + tan'(x)*y * ~ tan(x) + (1+x*x)*y * Therefore, for better accuracy in computing tan(x+y), let * 3 2 2 2 2 * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) * then * 3 2 * tan(x+y) = x + (T1*x + (x *(r+y)+y)) * * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) */ #include "math.h" #include "math_private.h" static const double xxx[] = { 3.33333333333334091986e-01, /* 3FD55555, 55555563 */ 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */ 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */ 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */ 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */ 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */ 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */ 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */ 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */ 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */ 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */ -1.85586374855275456654e-05, /* BEF375CB, DB605373 */ 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */ /* one */ 1.00000000000000000000e+00, /* 3FF00000, 00000000 */ /* pio4 */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */ /* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */ }; #define one xxx[13] #define pio4 xxx[14] #define pio4lo xxx[15] #define T xxx /* INDENT ON */ double __kernel_tan(double x, double y, int iy) { double z, r, v, w, s; int32_t ix, hx; GET_HIGH_WORD(hx,x); ix = hx & 0x7fffffff; /* high word of |x| */ if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */ if (hx < 0) { x = -x; y = -y; } z = pio4 - x; w = pio4lo - y; x = z + w; y = 0.0; } z = x * x; w = z * z; /* * Break x^5*(T[1]+x^2*T[2]+...) into * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) */ r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11])))); v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12]))))); s = z * x; r = y + z * (s * (r + v) + y); r += T[0] * s; w = x + r; if (ix >= 0x3FE59428) { v = (double) iy; return (double) (1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r))); } if (iy == 1) return w; else { /* * if allow error up to 2 ulp, simply return * -1.0 / (x+r) here */ /* compute -1.0 / (x+r) accurately */ double a, t; z = w; SET_LOW_WORD(z,0); v = r - (z - x); /* z+v = r+x */ t = a = -1.0 / w; /* a = -1.0/w */ SET_LOW_WORD(t,0); s = 1.0 + t * z; return t + a * (s + t * v); } } diff --git a/lib/msun/src/k_tanf.c b/lib/msun/src/k_tanf.c index 6ab7be71e323..83bfad9bbb9a 100644 --- a/lib/msun/src/k_tanf.c +++ b/lib/msun/src/k_tanf.c @@ -1,65 +1,61 @@ /* k_tanf.c -- float version of k_tan.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#ifndef INLINE_KERNEL_TANDF -#include -#endif - #include "math.h" #include "math_private.h" /* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */ static const double T[] = { 0x15554d3418c99f.0p-54, /* 0.333331395030791399758 */ 0x1112fd38999f72.0p-55, /* 0.133392002712976742718 */ 0x1b54c91d865afe.0p-57, /* 0.0533812378445670393523 */ 0x191df3908c33ce.0p-58, /* 0.0245283181166547278873 */ 0x185dadfcecf44e.0p-61, /* 0.00297435743359967304927 */ 0x1362b9bf971bcd.0p-59, /* 0.00946564784943673166728 */ }; #ifdef INLINE_KERNEL_TANDF static __inline #endif float __kernel_tandf(double x, int iy) { double z,r,w,s,t,u; z = x*x; /* * Split up the polynomial into small independent terms to give * opportunities for parallel evaluation. The chosen splitting is * micro-optimized for Athlons (XP, X64). It costs 2 multiplications * relative to Horner's method on sequential machines. * * We add the small terms from lowest degree up for efficiency on * non-sequential machines (the lowest degree terms tend to be ready * earlier). Apart from this, we don't care about order of * operations, and don't need to care since we have precision to * spare. However, the chosen splitting is good for accuracy too, * and would give results as accurate as Horner's method if the * small terms were added from highest degree down. */ r = T[4]+z*T[5]; t = T[2]+z*T[3]; w = z*z; s = z*x; u = T[0]+z*T[1]; r = (x+s*u)+(s*w)*(t+w*r); if(iy==1) return r; else return -1.0/r; } diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h index 8e72beb757f8..405434752336 100644 --- a/lib/msun/src/math.h +++ b/lib/msun/src/math.h @@ -1,514 +1,513 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * from: @(#)fdlibm.h 5.1 93/09/24 */ #ifndef _MATH_H_ #define _MATH_H_ -#include #include #include /* * ANSI/POSIX */ extern const union __infinity_un { unsigned char __uc[8]; double __ud; } __infinity; extern const union __nan_un { unsigned char __uc[sizeof(float)]; float __uf; } __nan; #if __GNUC_PREREQ__(3, 3) #define __MATH_BUILTIN_CONSTANTS #endif #if __GNUC_PREREQ__(3, 0) #define __MATH_BUILTIN_RELOPS #endif #ifdef __MATH_BUILTIN_CONSTANTS #define HUGE_VAL __builtin_huge_val() #else #define HUGE_VAL (__infinity.__ud) #endif #if __ISO_C_VISIBLE >= 1999 #define FP_ILOGB0 (-__INT_MAX) #define FP_ILOGBNAN __INT_MAX #ifdef __MATH_BUILTIN_CONSTANTS #define HUGE_VALF __builtin_huge_valf() #define HUGE_VALL __builtin_huge_vall() #define INFINITY __builtin_inff() #define NAN __builtin_nanf("") #else #define HUGE_VALF (float)HUGE_VAL #define HUGE_VALL (long double)HUGE_VAL #define INFINITY HUGE_VALF #define NAN (__nan.__uf) #endif /* __MATH_BUILTIN_CONSTANTS */ #define MATH_ERRNO 1 #define MATH_ERREXCEPT 2 #define math_errhandling MATH_ERREXCEPT #define FP_FAST_FMAF 1 /* Symbolic constants to classify floating point numbers. */ #define FP_INFINITE 0x01 #define FP_NAN 0x02 #define FP_NORMAL 0x04 #define FP_SUBNORMAL 0x08 #define FP_ZERO 0x10 #if __STDC_VERSION__ >= 201112L || __has_extension(c_generic_selections) #define __fp_type_select(x, f, d, ld) __extension__ _Generic((x), \ float: f(x), \ double: d(x), \ long double: ld(x)) #elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) #define __fp_type_select(x, f, d, ld) __builtin_choose_expr( \ __builtin_types_compatible_p(__typeof(x), long double), ld(x), \ __builtin_choose_expr( \ __builtin_types_compatible_p(__typeof(x), double), d(x), \ __builtin_choose_expr( \ __builtin_types_compatible_p(__typeof(x), float), f(x), (void)0))) #else #define __fp_type_select(x, f, d, ld) \ ((sizeof(x) == sizeof(float)) ? f(x) \ : (sizeof(x) == sizeof(double)) ? d(x) \ : ld(x)) #endif #define fpclassify(x) \ __fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyl) #define isfinite(x) __fp_type_select(x, __isfinitef, __isfinite, __isfinitel) #define isinf(x) __fp_type_select(x, __isinff, __isinf, __isinfl) #define isnan(x) \ __fp_type_select(x, __inline_isnanf, __inline_isnan, __inline_isnanl) #define isnormal(x) __fp_type_select(x, __isnormalf, __isnormal, __isnormall) #ifdef __MATH_BUILTIN_RELOPS #define isgreater(x, y) __builtin_isgreater((x), (y)) #define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y)) #define isless(x, y) __builtin_isless((x), (y)) #define islessequal(x, y) __builtin_islessequal((x), (y)) #define islessgreater(x, y) __builtin_islessgreater((x), (y)) #define isunordered(x, y) __builtin_isunordered((x), (y)) #else #define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y)) #define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y)) #define isless(x, y) (!isunordered((x), (y)) && (x) < (y)) #define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y)) #define islessgreater(x, y) (!isunordered((x), (y)) && \ ((x) > (y) || (y) > (x))) #define isunordered(x, y) (isnan(x) || isnan(y)) #endif /* __MATH_BUILTIN_RELOPS */ #define signbit(x) __fp_type_select(x, __signbitf, __signbit, __signbitl) typedef __double_t double_t; typedef __float_t float_t; #endif /* __ISO_C_VISIBLE >= 1999 */ /* * XOPEN/SVID */ #if __BSD_VISIBLE || __XSI_VISIBLE #define M_E 2.7182818284590452354 /* e */ #define M_LOG2E 1.4426950408889634074 /* log 2e */ #define M_LOG10E 0.43429448190325182765 /* log 10e */ #define M_LN2 0.69314718055994530942 /* log e2 */ #define M_LN10 2.30258509299404568402 /* log e10 */ #define M_PI 3.14159265358979323846 /* pi */ #define M_PI_2 1.57079632679489661923 /* pi/2 */ #define M_PI_4 0.78539816339744830962 /* pi/4 */ #define M_1_PI 0.31830988618379067154 /* 1/pi */ #define M_2_PI 0.63661977236758134308 /* 2/pi */ #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #define MAXFLOAT ((float)3.40282346638528860e+38) extern int signgam; #endif /* __BSD_VISIBLE || __XSI_VISIBLE */ #if __BSD_VISIBLE #if 0 /* Old value from 4.4BSD-Lite math.h; this is probably better. */ #define HUGE HUGE_VAL #else #define HUGE MAXFLOAT #endif #endif /* __BSD_VISIBLE */ /* * Most of these functions depend on the rounding mode and have the side * effect of raising floating-point exceptions, so they are not declared * as __pure2. In C99, FENV_ACCESS affects the purity of these functions. */ __BEGIN_DECLS /* * ANSI/POSIX */ int __fpclassifyd(double) __pure2; int __fpclassifyf(float) __pure2; int __fpclassifyl(long double) __pure2; int __isfinitef(float) __pure2; int __isfinite(double) __pure2; int __isfinitel(long double) __pure2; int __isinff(float) __pure2; int __isinf(double) __pure2; int __isinfl(long double) __pure2; int __isnormalf(float) __pure2; int __isnormal(double) __pure2; int __isnormall(long double) __pure2; int __signbit(double) __pure2; int __signbitf(float) __pure2; int __signbitl(long double) __pure2; static __inline int __inline_isnan(__const double __x) { return (__x != __x); } static __inline int __inline_isnanf(__const float __x) { return (__x != __x); } static __inline int __inline_isnanl(__const long double __x) { return (__x != __x); } /* * Define the following aliases, for compatibility with glibc and CUDA. */ #define __isnan __inline_isnan #define __isnanf __inline_isnanf /* * Version 2 of the Single UNIX Specification (UNIX98) defined isnan() and * isinf() as functions taking double. C99, and the subsequent POSIX revisions * (SUSv3, POSIX.1-2001, define it as a macro that accepts any real floating * point type. If we are targeting SUSv2 and C99 or C11 (or C++11) then we * expose the newer definition, assuming that the language spec takes * precedence over the operating system interface spec. */ #if __XSI_VISIBLE > 0 && __XSI_VISIBLE < 600 && __ISO_C_VISIBLE < 1999 #undef isinf #undef isnan int isinf(double); int isnan(double); #endif double acos(double); double asin(double); double atan(double); double atan2(double, double); double cos(double); double sin(double); double tan(double); double cosh(double); double sinh(double); double tanh(double); double exp(double); double frexp(double, int *); /* fundamentally !__pure2 */ double ldexp(double, int); double log(double); double log10(double); double modf(double, double *); /* fundamentally !__pure2 */ double pow(double, double); double sqrt(double); double ceil(double); double fabs(double) __pure2; double floor(double); double fmod(double, double); /* * These functions are not in C90. */ #if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE double acosh(double); double asinh(double); double atanh(double); double cbrt(double); double erf(double); double erfc(double); double exp2(double); double expm1(double); double fma(double, double, double); double hypot(double, double); int ilogb(double) __pure2; double lgamma(double); long long llrint(double); long long llround(double); double log1p(double); double log2(double); double logb(double); long lrint(double); long lround(double); double nan(const char *) __pure2; double nextafter(double, double); double remainder(double, double); double remquo(double, double, int *); double rint(double); #endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE */ #if __BSD_VISIBLE || __XSI_VISIBLE double j0(double); double j1(double); double jn(int, double); double y0(double); double y1(double); double yn(int, double); #if __XSI_VISIBLE <= 500 || __BSD_VISIBLE double gamma(double); #endif #if __XSI_VISIBLE <= 600 || __BSD_VISIBLE double scalb(double, double); #endif #endif /* __BSD_VISIBLE || __XSI_VISIBLE */ #if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 double copysign(double, double) __pure2; double fdim(double, double); double fmax(double, double) __pure2; double fmin(double, double) __pure2; double nearbyint(double); double round(double); double scalbln(double, long); double scalbn(double, int); double tgamma(double); double trunc(double); #endif /* * BSD math library entry points */ #if __BSD_VISIBLE double drem(double, double); int finite(double) __pure2; int isnanf(float) __pure2; /* * Reentrant version of gamma & lgamma; passes signgam back by reference * as the second argument; user must allocate space for signgam. */ double gamma_r(double, int *); double lgamma_r(double, int *); /* * IEEE Test Vector */ double significand(double); #endif /* __BSD_VISIBLE */ /* float versions of ANSI/POSIX functions */ #if __ISO_C_VISIBLE >= 1999 float acosf(float); float asinf(float); float atanf(float); float atan2f(float, float); float cosf(float); float sinf(float); float tanf(float); float coshf(float); float sinhf(float); float tanhf(float); float exp2f(float); float expf(float); float expm1f(float); float frexpf(float, int *); /* fundamentally !__pure2 */ int ilogbf(float) __pure2; float ldexpf(float, int); float log10f(float); float log1pf(float); float log2f(float); float logf(float); float modff(float, float *); /* fundamentally !__pure2 */ float powf(float, float); float sqrtf(float); float ceilf(float); float fabsf(float) __pure2; float floorf(float); float fmodf(float, float); float roundf(float); float erff(float); float erfcf(float); float hypotf(float, float); float lgammaf(float); float tgammaf(float); float acoshf(float); float asinhf(float); float atanhf(float); float cbrtf(float); float logbf(float); float copysignf(float, float) __pure2; long long llrintf(float); long long llroundf(float); long lrintf(float); long lroundf(float); float nanf(const char *) __pure2; float nearbyintf(float); float nextafterf(float, float); float remainderf(float, float); float remquof(float, float, int *); float rintf(float); float scalblnf(float, long); float scalbnf(float, int); float truncf(float); float fdimf(float, float); float fmaf(float, float, float); float fmaxf(float, float) __pure2; float fminf(float, float) __pure2; #endif /* * float versions of BSD math library entry points */ #if __BSD_VISIBLE float dremf(float, float); int finitef(float) __pure2; float gammaf(float); float j0f(float); float j1f(float); float jnf(int, float); float scalbf(float, float); float y0f(float); float y1f(float); float ynf(int, float); /* * Float versions of reentrant version of gamma & lgamma; passes * signgam back by reference as the second argument; user must * allocate space for signgam. */ float gammaf_r(float, int *); float lgammaf_r(float, int *); /* * float version of IEEE Test Vector */ float significandf(float); #endif /* __BSD_VISIBLE */ /* * long double versions of ISO/POSIX math functions */ #if __ISO_C_VISIBLE >= 1999 long double acoshl(long double); long double acosl(long double); long double asinhl(long double); long double asinl(long double); long double atan2l(long double, long double); long double atanhl(long double); long double atanl(long double); long double cbrtl(long double); long double ceill(long double); long double copysignl(long double, long double) __pure2; long double coshl(long double); long double cosl(long double); long double erfcl(long double); long double erfl(long double); long double exp2l(long double); long double expl(long double); long double expm1l(long double); long double fabsl(long double) __pure2; long double fdiml(long double, long double); long double floorl(long double); long double fmal(long double, long double, long double); long double fmaxl(long double, long double) __pure2; long double fminl(long double, long double) __pure2; long double fmodl(long double, long double); long double frexpl(long double, int *); /* fundamentally !__pure2 */ long double hypotl(long double, long double); int ilogbl(long double) __pure2; long double ldexpl(long double, int); long double lgammal(long double); long long llrintl(long double); long long llroundl(long double); long double log10l(long double); long double log1pl(long double); long double log2l(long double); long double logbl(long double); long double logl(long double); long lrintl(long double); long lroundl(long double); long double modfl(long double, long double *); /* fundamentally !__pure2 */ long double nanl(const char *) __pure2; long double nearbyintl(long double); long double nextafterl(long double, long double); double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); long double powl(long double, long double); long double remainderl(long double, long double); long double remquol(long double, long double, int *); long double rintl(long double); long double roundl(long double); long double scalblnl(long double, long); long double scalbnl(long double, int); long double sinhl(long double); long double sinl(long double); long double sqrtl(long double); long double tanhl(long double); long double tanl(long double); long double tgammal(long double); long double truncl(long double); #endif /* __ISO_C_VISIBLE >= 1999 */ #if __BSD_VISIBLE long double lgammal_r(long double, int *); void sincos(double, double *, double *); void sincosf(float, float *, float *); void sincosl(long double, long double *, long double *); double cospi(double); float cospif(float); long double cospil(long double); double sinpi(double); float sinpif(float); long double sinpil(long double); double tanpi(double); float tanpif(float); long double tanpil(long double); #endif __END_DECLS #endif /* !_MATH_H_ */ diff --git a/lib/msun/src/s_asinh.c b/lib/msun/src/s_asinh.c index a8bad118f6b3..4b221e0abf7e 100644 --- a/lib/msun/src/s_asinh.c +++ b/lib/msun/src/s_asinh.c @@ -1,60 +1,59 @@ /* @(#)s_asinh.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* asinh(x) * Method : * Based on * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] * we have * asinh(x) := x if 1+x*x=1, * := sign(x)*(log(x)+ln2)) for large |x|, else * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) */ #include #include "math.h" #include "math_private.h" static const double one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ huge= 1.00000000000000000000e+300; double asinh(double x) { double t,w; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */ if(ix< 0x3e300000) { /* |x|<2**-28 */ if(huge+x>one) return x; /* return x inexact except 0 */ } if(ix>0x41b00000) { /* |x| > 2**28 */ w = log(fabs(x))+ln2; } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ t = fabs(x); w = log(2.0*t+one/(sqrt(x*x+one)+t)); } else { /* 2.0 > |x| > 2**-28 */ t = x*x; w =log1p(fabs(x)+t/(one+sqrt(one+t))); } if(hx>0) return w; else return -w; } #if LDBL_MANT_DIG == 53 __weak_reference(asinh, asinhl); #endif diff --git a/lib/msun/src/s_asinhf.c b/lib/msun/src/s_asinhf.c index 822b0187ad09..4e622d5f6242 100644 --- a/lib/msun/src/s_asinhf.c +++ b/lib/msun/src/s_asinhf.c @@ -1,46 +1,45 @@ /* s_asinhf.c -- float version of s_asinh.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0000000000e+00, /* 0x3F800000 */ ln2 = 6.9314718246e-01, /* 0x3f317218 */ huge= 1.0000000000e+30; float asinhf(float x) { float t,w; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) return x+x; /* x is inf or NaN */ if(ix< 0x31800000) { /* |x|<2**-28 */ if(huge+x>one) return x; /* return x inexact except 0 */ } if(ix>0x4d800000) { /* |x| > 2**28 */ w = logf(fabsf(x))+ln2; } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ t = fabsf(x); w = logf((float)2.0*t+one/(sqrtf(x*x+one)+t)); } else { /* 2.0 > |x| > 2**-28 */ t = x*x; w =log1pf(fabsf(x)+t/(one+sqrtf(one+t))); } if(hx>0) return w; else return -w; } diff --git a/lib/msun/src/s_asinhl.c b/lib/msun/src/s_asinhl.c index d80405821ff4..4f079da903fc 100644 --- a/lib/msun/src/s_asinhl.c +++ b/lib/msun/src/s_asinhl.c @@ -1,89 +1,88 @@ /* from: FreeBSD: head/lib/msun/src/e_acosh.c 176451 2008-02-22 02:30:36Z das */ /* @(#)s_asinh.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See s_asinh.c for complete comments. * * Converted to long double by David Schultz and * Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" /* EXP_LARGE is the threshold above which we use asinh(x) ~= log(2x). */ /* EXP_TINY is the threshold below which we use asinh(x) ~= x. */ #if LDBL_MANT_DIG == 64 #define EXP_LARGE 34 #define EXP_TINY -34 #elif LDBL_MANT_DIG == 113 #define EXP_LARGE 58 #define EXP_TINY -58 #else #error "Unsupported long double format" #endif #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const double one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ huge= 1.00000000000000000000e+300; #if LDBL_MANT_DIG == 64 static const union IEEEl2bits u_ln2 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L); #define ln2 u_ln2.e #elif LDBL_MANT_DIG == 113 static const long double ln2 = 6.93147180559945309417232121458176568e-1L; /* 0x162e42fefa39ef35793c7673007e6.0p-113 */ #else #error "Unsupported long double format" #endif long double asinhl(long double x) { long double t, w; uint16_t hx, ix; ENTERI(); GET_LDBL_EXPSIGN(hx, x); ix = hx & 0x7fff; if (ix >= 0x7fff) RETURNI(x+x); /* x is inf, NaN or misnormal */ if (ix < BIAS + EXP_TINY) { /* |x| < TINY, or misnormal */ if (huge + x > one) RETURNI(x); /* return x inexact except 0 */ } if (ix >= BIAS + EXP_LARGE) { /* |x| >= LARGE, or misnormal */ w = logl(fabsl(x))+ln2; } else if (ix >= 0x4000) { /* LARGE > |x| >= 2.0, or misnormal */ t = fabsl(x); w = logl(2.0*t+one/(sqrtl(x*x+one)+t)); } else { /* 2.0 > |x| >= TINY, or misnormal */ t = x*x; w =log1pl(fabsl(x)+t/(one+sqrtl(one+t))); } RETURNI((hx & 0x8000) == 0 ? w : -w); } diff --git a/lib/msun/src/s_atan.c b/lib/msun/src/s_atan.c index d2bfacf52ab6..c0781081bf1d 100644 --- a/lib/msun/src/s_atan.c +++ b/lib/msun/src/s_atan.c @@ -1,122 +1,121 @@ /* @(#)s_atan.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* atan(x) * Method * 1. Reduce x to positive by atan(x) = -atan(-x). * 2. According to the integer k=4t+0.25 chopped, t=x, the argument * is further reduced to one of the following intervals and the * arctangent of t is evaluated by the corresponding formula: * * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const double atanhi[] = { 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ }; static const double atanlo[] = { 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ }; static const double aT[] = { 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ }; static const double one = 1.0, huge = 1.0e300; double atan(double x) { double w,s1,s2,z; int32_t ix,hx,id; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x44100000) { /* if |x| >= 2^66 */ u_int32_t low; GET_LOW_WORD(low,x); if(ix>0x7ff00000|| (ix==0x7ff00000&&(low!=0))) return x+x; /* NaN */ if(hx>0) return atanhi[3]+*(volatile double *)&atanlo[3]; else return -atanhi[3]-*(volatile double *)&atanlo[3]; } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ if (ix < 0x3e400000) { /* |x| < 2^-27 */ if(huge+x>one) return x; /* raise inexact */ } id = -1; } else { x = fabs(x); if (ix < 0x3ff30000) { /* |x| < 1.1875 */ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ id = 0; x = (2.0*x-one)/(2.0+x); } else { /* 11/16<=|x|< 19/16 */ id = 1; x = (x-one)/(x+one); } } else { if (ix < 0x40038000) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(one+1.5*x); } else { /* 2.4375 <= |x| < 2^66 */ id = 3; x = -1.0/x; } }} /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); if (id<0) return x - x*(s1+s2); else { z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return (hx<0)? -z:z; } } #if LDBL_MANT_DIG == 53 __weak_reference(atan, atanl); #endif diff --git a/lib/msun/src/s_atanf.c b/lib/msun/src/s_atanf.c index 30666fe0b66a..2c38014ac6c8 100644 --- a/lib/msun/src/s_atanf.c +++ b/lib/msun/src/s_atanf.c @@ -1,90 +1,89 @@ /* s_atanf.c -- float version of s_atan.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float atanhi[] = { 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ }; static const float atanlo[] = { 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ }; static const float aT[] = { 3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02, }; static const float one = 1.0, huge = 1.0e30; float atanf(float x) { float w,s1,s2,z; int32_t ix,hx,id; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x4c800000) { /* if |x| >= 2**26 */ if(ix>0x7f800000) return x+x; /* NaN */ if(hx>0) return atanhi[3]+*(volatile float *)&atanlo[3]; else return -atanhi[3]-*(volatile float *)&atanlo[3]; } if (ix < 0x3ee00000) { /* |x| < 0.4375 */ if (ix < 0x39800000) { /* |x| < 2**-12 */ if(huge+x>one) return x; /* raise inexact */ } id = -1; } else { x = fabsf(x); if (ix < 0x3f980000) { /* |x| < 1.1875 */ if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */ id = 0; x = ((float)2.0*x-one)/((float)2.0+x); } else { /* 11/16<=|x|< 19/16 */ id = 1; x = (x-one)/(x+one); } } else { if (ix < 0x401c0000) { /* |x| < 2.4375 */ id = 2; x = (x-(float)1.5)/(one+(float)1.5*x); } else { /* 2.4375 <= |x| < 2**26 */ id = 3; x = -(float)1.0/x; } }} /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*aT[4])); s2 = w*(aT[1]+w*aT[3]); if (id<0) return x - x*(s1+s2); else { z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return (hx<0)? -z:z; } } diff --git a/lib/msun/src/s_atanl.c b/lib/msun/src/s_atanl.c index b85cb131035f..a030c212630a 100644 --- a/lib/msun/src/s_atanl.c +++ b/lib/msun/src/s_atanl.c @@ -1,83 +1,82 @@ /* @(#)s_atan.c 5.1 93/09/24 */ /* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See comments in s_atan.c. * Converted to long double by David Schultz . */ #include #include "invtrig.h" #include "math.h" #include "math_private.h" static const long double one = 1.0, huge = 1.0e300; long double atanl(long double x) { union IEEEl2bits u; long double w,s1,s2,z; int id; int16_t expsign, expt; int32_t expman; u.e = x; expsign = u.xbits.expsign; expt = expsign & 0x7fff; if(expt >= ATAN_CONST) { /* if |x| is large, atan(x)~=pi/2 */ if(expt == BIAS + LDBL_MAX_EXP && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0) return x+x; /* NaN */ if(expsign>0) return atanhi[3]+atanlo[3]; else return -atanhi[3]-atanlo[3]; } /* Extract the exponent and the first few bits of the mantissa. */ /* XXX There should be a more convenient way to do this. */ expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff); if (expman < ((BIAS - 2) << 8) + 0xc0) { /* |x| < 0.4375 */ if (expt < ATAN_LINEAR) { /* if |x| is small, atanl(x)~=x */ if(huge+x>one) return x; /* raise inexact */ } id = -1; } else { x = fabsl(x); if (expman < (BIAS << 8) + 0x30) { /* |x| < 1.1875 */ if (expman < ((BIAS - 1) << 8) + 0x60) { /* 7/16 <=|x|<11/16 */ id = 0; x = (2.0*x-one)/(2.0+x); } else { /* 11/16<=|x|< 19/16 */ id = 1; x = (x-one)/(x+one); } } else { if (expman < ((BIAS + 1) << 8) + 0x38) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(one+1.5*x); } else { /* 2.4375 <= |x| < 2^ATAN_CONST */ id = 3; x = -1.0/x; } }} /* end of argument reduction */ z = x*x; w = z*z; /* break sum aT[i]z**(i+1) into odd and even poly */ s1 = z*T_even(w); s2 = w*T_odd(w); if (id<0) return x - x*(s1+s2); else { z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return (expsign<0)? -z:z; } } diff --git a/lib/msun/src/s_carg.c b/lib/msun/src/s_carg.c index 45714bbdb18a..ea7edfdf0835 100644 --- a/lib/msun/src/s_carg.c +++ b/lib/msun/src/s_carg.c @@ -1,38 +1,37 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include double carg(double complex z) { return (atan2(cimag(z), creal(z))); } diff --git a/lib/msun/src/s_cargf.c b/lib/msun/src/s_cargf.c index c4d53006b542..25ab65ef7f9f 100644 --- a/lib/msun/src/s_cargf.c +++ b/lib/msun/src/s_cargf.c @@ -1,38 +1,37 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include float cargf(float complex z) { return (atan2f(cimagf(z), crealf(z))); } diff --git a/lib/msun/src/s_cargl.c b/lib/msun/src/s_cargl.c index d7f8206e9608..8a1a108705d4 100644 --- a/lib/msun/src/s_cargl.c +++ b/lib/msun/src/s_cargl.c @@ -1,38 +1,37 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include long double cargl(long double complex z) { return (atan2l(cimagl(z), creall(z))); } diff --git a/lib/msun/src/s_cbrt.c b/lib/msun/src/s_cbrt.c index afb601bf0fb6..bc9c35f03741 100644 --- a/lib/msun/src/s_cbrt.c +++ b/lib/msun/src/s_cbrt.c @@ -1,116 +1,115 @@ /* @(#)s_cbrt.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * Optimized by Bruce D. Evans. */ -#include #include #include "math.h" #include "math_private.h" /* cbrt(x) * Return cube root of x */ static const u_int32_t B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */ B2 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */ /* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */ static const double P0 = 1.87595182427177009643, /* 0x3ffe03e6, 0x0f61e692 */ P1 = -1.88497979543377169875, /* 0xbffe28e0, 0x92f02420 */ P2 = 1.621429720105354466140, /* 0x3ff9f160, 0x4a49d6c2 */ P3 = -0.758397934778766047437, /* 0xbfe844cb, 0xbee751d9 */ P4 = 0.145996192886612446982; /* 0x3fc2b000, 0xd4e4edd7 */ double cbrt(double x) { int32_t hx; union { double value; uint64_t bits; } u; double r,s,t=0.0,w; u_int32_t sign; u_int32_t high,low; EXTRACT_WORDS(hx,low,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ /* * Rough cbrt to 5 bits: * cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3) * where e is integral and >= 0, m is real and in [0, 1), and "/" and * "%" are integer division and modulus with rounding towards minus * infinity. The RHS is always >= the LHS and has a maximum relative * error of about 1 in 16. Adding a bias of -0.03306235651 to the * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE * floating point representation, for finite positive normal values, * ordinary integer division of the value in bits magically gives * almost exactly the RHS of the above provided we first subtract the * exponent bias (1023 for doubles) and later add it back. We do the * subtraction virtually to keep e >= 0 so that ordinary integer * division rounds towards minus infinity; this is also efficient. */ if(hx<0x00100000) { /* zero or subnormal? */ if((hx|low)==0) return(x); /* cbrt(0) is itself */ SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */ t*=x; GET_HIGH_WORD(high,t); INSERT_WORDS(t,sign|((high&0x7fffffff)/3+B2),0); } else INSERT_WORDS(t,sign|(hx/3+B1),0); /* * New cbrt to 23 bits: * cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x) * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r) * to within 2**-23.5 when |r - 1| < 1/10. The rough approximation * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this * gives us bounds for r = t**3/x. * * Try to optimize for parallel evaluation as in k_tanf.c. */ r=(t*t)*(t/x); t=t*((P0+r*(P1+r*P2))+((r*r)*r)*(P3+r*P4)); /* * Round t away from zero to 23 bits (sloppily except for ensuring that * the result is larger in magnitude than cbrt(x) but not much more than * 2 23-bit ulps larger). With rounding towards zero, the error bound * would be ~5/6 instead of ~4/6. With a maximum error of 2 23-bit ulps * in the rounded t, the infinite-precision error in the Newton * approximation barely affects third digit in the final error * 0.667; the error in the rounded t can be up to about 3 23-bit ulps * before the final error is larger than 0.667 ulps. */ u.value=t; u.bits=(u.bits+0x80000000)&0xffffffffc0000000ULL; t=u.value; /* one step Newton iteration to 53 bits with error < 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; /* error <= 0.5 ulps; |r| < |t| */ w=t+t; /* t+t is exact */ r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */ t=t+t*r; /* error <= (0.5 + 0.5/3) * ulp */ return(t); } #if (LDBL_MANT_DIG == 53) __weak_reference(cbrt, cbrtl); #endif diff --git a/lib/msun/src/s_cbrtf.c b/lib/msun/src/s_cbrtf.c index f013e1f1eb6f..a225d3edb982 100644 --- a/lib/msun/src/s_cbrtf.c +++ b/lib/msun/src/s_cbrtf.c @@ -1,71 +1,70 @@ /* s_cbrtf.c -- float version of s_cbrt.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Debugged and optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" /* cbrtf(x) * Return cube root of x */ static const unsigned B1 = 709958130, /* B1 = (127-127.0/3-0.03306235651)*2**23 */ B2 = 642849266; /* B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */ float cbrtf(float x) { double r,T; float t; int32_t hx; u_int32_t sign; u_int32_t high; GET_FLOAT_WORD(hx,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */ /* rough cbrt to 5 bits */ if(hx<0x00800000) { /* zero or subnormal? */ if(hx==0) return(x); /* cbrt(+-0) is itself */ SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */ t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,sign|((high&0x7fffffff)/3+B2)); } else SET_FLOAT_WORD(t,sign|(hx/3+B1)); /* * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In * double precision so that its terms can be arranged for efficiency * without causing overflow or underflow. */ T=t; r=T*T*T; T=T*((double)x+x+r)/(x+r+r); /* * Second step Newton iteration to 47 bits. In double precision for * efficiency and accuracy. */ r=T*T*T; T=T*((double)x+x+r)/(x+r+r); /* rounding to 24 bits is perfect in round-to-nearest mode */ return(T); } diff --git a/lib/msun/src/s_cbrtl.c b/lib/msun/src/s_cbrtl.c index 3ed939cccf92..f1950e2d4cef 100644 --- a/lib/msun/src/s_cbrtl.c +++ b/lib/msun/src/s_cbrtl.c @@ -1,141 +1,140 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * The argument reduction and testing for exceptional cases was * written by Steven G. Kargl with input from Bruce D. Evans * and David A. Schultz. */ -#include #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #define BIAS (LDBL_MAX_EXP - 1) static const unsigned B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */ long double cbrtl(long double x) { union IEEEl2bits u, v; long double r, s, t, w; double dr, dt, dx; float ft, fx; uint32_t hx; uint16_t expsign; int k; u.e = x; expsign = u.xbits.expsign; k = expsign & 0x7fff; /* * If x = +-Inf, then cbrt(x) = +-Inf. * If x = NaN, then cbrt(x) = NaN. */ if (k == BIAS + LDBL_MAX_EXP) return (x + x); ENTERI(); if (k == 0) { /* If x = +-0, then cbrt(x) = +-0. */ if ((u.bits.manh | u.bits.manl) == 0) RETURNI(x); /* Adjust subnormal numbers. */ u.e *= 0x1.0p514; k = u.bits.exp; k -= BIAS + 514; } else k -= BIAS; u.xbits.expsign = BIAS; v.e = 1; x = u.e; switch (k % 3) { case 1: case -2: x = 2*x; k--; break; case 2: case -1: x = 4*x; k -= 2; break; } v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3); /* * The following is the guts of s_cbrtf, with the handling of * special values removed and extra care for accuracy not taken, * but with most of the extra accuracy not discarded. */ /* ~5-bit estimate: */ fx = x; GET_FLOAT_WORD(hx, fx); SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1)); /* ~16-bit estimate: */ dx = x; dt = ft; dr = dt * dt * dt; dt = dt * (dx + dx + dr) / (dx + dr + dr); /* ~47-bit estimate: */ dr = dt * dt * dt; dt = dt * (dx + dx + dr) / (dx + dr + dr); #if LDBL_MANT_DIG == 64 /* * dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8). * Round it away from zero to 32 bits (32 so that t*t is exact, and * away from zero for technical reasons). */ volatile double vd2 = 0x1.0p32; volatile double vd1 = 0x1.0p-31; #define vd ((long double)vd2 + vd1) t = dt + vd - 0x1.0p32; #elif LDBL_MANT_DIG == 113 /* * Round dt away from zero to 47 bits. Since we don't trust the 47, * add 2 47-bit ulps instead of 1 to round up. Rounding is slow and * might be avoidable in this case, since on most machines dt will * have been evaluated in 53-bit precision and the technical reasons * for rounding up might not apply to either case in cbrtl() since * dt is much more accurate than needed. */ t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60; #else #error "Unsupported long double format" #endif /* * Final step Newton iteration to 64 or 113 bits with * error < 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; /* error <= 0.5 ulps; |r| < |t| */ w=t+t; /* t+t is exact */ r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */ t=t+t*r; /* error <= (0.5 + 0.5/3) * ulp */ t *= v.e; RETURNI(t); } diff --git a/lib/msun/src/s_ccosh.c b/lib/msun/src/s_ccosh.c index 95ed3a32ddd7..3d46c993c6f1 100644 --- a/lib/msun/src/s_ccosh.c +++ b/lib/msun/src/s_ccosh.c @@ -1,157 +1,156 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Hyperbolic cosine of a complex argument z = x + i y. * * cosh(z) = cosh(x+iy) * = cosh(x) cos(y) + i sinh(x) sin(y). * * Exceptional values are noted in the comments within the source code. * These values and the return value were taken from n1124.pdf. * The sign of the result for some exceptional values is unspecified but * must satisfy both cosh(conj(z)) == conj(cosh(z)) and cosh(-z) == cosh(z). */ -#include #include #include #include "math_private.h" static const double huge = 0x1p1023; double complex ccosh(double complex z) { double x, y, h; int32_t hx, hy, ix, iy, lx, ly; x = creal(z); y = cimag(z); EXTRACT_WORDS(hx, lx, x); EXTRACT_WORDS(hy, ly, y); ix = 0x7fffffff & hx; iy = 0x7fffffff & hy; /* Handle the nearly-non-exceptional cases where x and y are finite. */ if (ix < 0x7ff00000 && iy < 0x7ff00000) { if ((iy | ly) == 0) return (CMPLX(cosh(x), x * y)); if (ix < 0x40360000) /* |x| < 22: normal case */ return (CMPLX(cosh(x) * cos(y), sinh(x) * sin(y))); /* |x| >= 22, so cosh(x) ~= exp(|x|) */ if (ix < 0x40862e42) { /* x < 710: exp(|x|) won't overflow */ h = exp(fabs(x)) * 0.5; return (CMPLX(h * cos(y), copysign(h, x) * sin(y))); } else if (ix < 0x4096bbaa) { /* x < 1455: scale to avoid overflow */ z = __ldexp_cexp(CMPLX(fabs(x), y), -1); return (CMPLX(creal(z), cimag(z) * copysign(1, x))); } else { /* x >= 1455: the result always overflows */ h = huge * x; return (CMPLX(h * h * cos(y), h * sin(y))); } } /* * cosh(+-0 +- I Inf) = dNaN + I (+-)(+-)0. * The sign of 0 in the result is unspecified. Choice = product * of the signs of the argument. Raise the invalid floating-point * exception. * * cosh(+-0 +- I NaN) = d(NaN) + I (+-)(+-)0. * The sign of 0 in the result is unspecified. Choice = product * of the signs of the argument. */ if ((ix | lx) == 0) /* && iy >= 0x7ff00000 */ return (CMPLX(y - y, x * copysign(0, y))); /* * cosh(+-Inf +- I 0) = +Inf + I (+-)(+-)0. * * cosh(NaN +- I 0) = d(NaN) + I (+-)(+-)0. * The sign of 0 in the result is unspecified. Choice = product * of the signs of the argument. */ if ((iy | ly) == 0) /* && ix >= 0x7ff00000 */ return (CMPLX(x * x, copysign(0, x) * y)); /* * cosh(x +- I Inf) = dNaN + I dNaN. * Raise the invalid floating-point exception for finite nonzero x. * * cosh(x + I NaN) = d(NaN) + I d(NaN). * Optionally raises the invalid floating-point exception for finite * nonzero x. Choice = don't raise (except for signaling NaNs). */ if (ix < 0x7ff00000) /* && iy >= 0x7ff00000 */ return (CMPLX(y - y, x * (y - y))); /* * cosh(+-Inf + I NaN) = +Inf + I d(NaN). * * cosh(+-Inf +- I Inf) = +Inf + I dNaN. * The sign of Inf in the result is unspecified. Choice = always +. * Raise the invalid floating-point exception. * * cosh(+-Inf + I y) = +Inf cos(y) +- I Inf sin(y) */ if (ix == 0x7ff00000 && lx == 0) { if (iy >= 0x7ff00000) return (CMPLX(INFINITY, x * (y - y))); return (CMPLX(INFINITY * cos(y), x * sin(y))); } /* * cosh(NaN + I NaN) = d(NaN) + I d(NaN). * * cosh(NaN +- I Inf) = d(NaN) + I d(NaN). * Optionally raises the invalid floating-point exception. * Choice = raise. * * cosh(NaN + I y) = d(NaN) + I d(NaN). * Optionally raises the invalid floating-point exception for finite * nonzero y. Choice = don't raise (except for signaling NaNs). */ return (CMPLX(((long double)x * x) * (y - y), ((long double)x + x) * (y - y))); } double complex ccos(double complex z) { /* ccos(z) = ccosh(I * z) */ return (ccosh(CMPLX(-cimag(z), creal(z)))); } diff --git a/lib/msun/src/s_ccoshf.c b/lib/msun/src/s_ccoshf.c index ba97a390c832..aeb2dec23677 100644 --- a/lib/msun/src/s_ccoshf.c +++ b/lib/msun/src/s_ccoshf.c @@ -1,102 +1,101 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Float version of ccosh(). See s_ccosh.c for details. */ -#include #include #include #include "math_private.h" static const float huge = 0x1p127; float complex ccoshf(float complex z) { float x, y, h; int32_t hx, hy, ix, iy; x = crealf(z); y = cimagf(z); GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = 0x7fffffff & hx; iy = 0x7fffffff & hy; if (ix < 0x7f800000 && iy < 0x7f800000) { if (iy == 0) return (CMPLXF(coshf(x), x * y)); if (ix < 0x41100000) /* |x| < 9: normal case */ return (CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y))); /* |x| >= 9, so cosh(x) ~= exp(|x|) */ if (ix < 0x42b17218) { /* x < 88.7: expf(|x|) won't overflow */ h = expf(fabsf(x)) * 0.5F; return (CMPLXF(h * cosf(y), copysignf(h, x) * sinf(y))); } else if (ix < 0x4340b1e7) { /* x < 192.7: scale to avoid overflow */ z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); return (CMPLXF(crealf(z), cimagf(z) * copysignf(1, x))); } else { /* x >= 192.7: the result always overflows */ h = huge * x; return (CMPLXF(h * h * cosf(y), h * sinf(y))); } } if (ix == 0) /* && iy >= 0x7f800000 */ return (CMPLXF(y - y, x * copysignf(0, y))); if (iy == 0) /* && ix >= 0x7f800000 */ return (CMPLXF(x * x, copysignf(0, x) * y)); if (ix < 0x7f800000) /* && iy >= 0x7f800000 */ return (CMPLXF(y - y, x * (y - y))); if (ix == 0x7f800000) { if (iy >= 0x7f800000) return (CMPLXF(INFINITY, x * (y - y))); return (CMPLXF(INFINITY * cosf(y), x * sinf(y))); } return (CMPLXF(((long double)x * x) * (y - y), ((long double)x + x) * (y - y))); } float complex ccosf(float complex z) { return (ccoshf(CMPLXF(-cimagf(z), crealf(z)))); } diff --git a/lib/msun/src/s_ceil.c b/lib/msun/src/s_ceil.c index 9c041b2a94e1..fdb014f1c7ae 100644 --- a/lib/msun/src/s_ceil.c +++ b/lib/msun/src/s_ceil.c @@ -1,75 +1,74 @@ /* @(#)s_ceil.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * ceil(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to ceil(x). */ #include #include "math.h" #include "math_private.h" static const double huge = 1.0e300; double ceil(double x) { int32_t i0,i1,j0; u_int32_t i,j; EXTRACT_WORDS(i0,i1,x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ if(i0<0) {i0=0x80000000;i1=0;} else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} } } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0>0) i0 += (0x00100000)>>j0; i0 &= (~i); i1=0; } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((u_int32_t)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0>0) { if(j0==20) i0+=1; else { j = i1 + (1<<(52-j0)); if(j #include "math.h" #include "math_private.h" static const float huge = 1.0e30; float ceilf(float x) { int32_t i0,j0; u_int32_t i; GET_FLOAT_WORD(i0,x); j0 = ((i0>>23)&0xff)-0x7f; if(j0<23) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ if(i0<0) {i0=0x80000000;} else if(i0!=0) { i0=0x3f800000;} } } else { i = (0x007fffff)>>j0; if((i0&i)==0) return x; /* x is integral */ if(huge+x>(float)0.0) { /* raise inexact flag */ if(i0>0) i0 += (0x00800000)>>j0; i0 &= (~i); } } } else { if(j0==0x80) return x+x; /* inf or NaN */ else return x; /* x is integral */ } SET_FLOAT_WORD(x,i0); return x; } diff --git a/lib/msun/src/s_ceill.c b/lib/msun/src/s_ceill.c index 28c0881e8da6..feb81f86fafd 100644 --- a/lib/msun/src/s_ceill.c +++ b/lib/msun/src/s_ceill.c @@ -1,99 +1,98 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * From: @(#)s_ceil.c 5.1 93/09/24 */ -#include /* * ceill(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to ceill(x). */ #include #include #include #include "fpmath.h" #ifdef LDBL_IMPLICIT_NBIT #define MANH_SIZE (LDBL_MANH_SIZE + 1) #define INC_MANH(u, c) do { \ uint64_t o = u.bits.manh; \ u.bits.manh += (c); \ if (u.bits.manh < o) \ u.bits.exp++; \ } while (0) #else #define MANH_SIZE LDBL_MANH_SIZE #define INC_MANH(u, c) do { \ uint64_t o = u.bits.manh; \ u.bits.manh += (c); \ if (u.bits.manh < o) { \ u.bits.exp++; \ u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \ } \ } while (0) #endif static const long double huge = 1.0e300; long double ceill(long double x) { union IEEEl2bits u = { .e = x }; int e = u.bits.exp - LDBL_MAX_EXP + 1; if (e < MANH_SIZE - 1) { if (e < 0) { /* raise inexact if x != 0 */ if (huge + x > 0.0) if (u.bits.exp > 0 || (u.bits.manh | u.bits.manl) != 0) u.e = u.bits.sign ? -0.0 : 1.0; } else { uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); if (((u.bits.manh & m) | u.bits.manl) == 0) return (x); /* x is integral */ if (!u.bits.sign) { #ifdef LDBL_IMPLICIT_NBIT if (e == 0) u.bits.exp++; else #endif INC_MANH(u, 1llu << (MANH_SIZE - e - 1)); } if (huge + x > 0.0) { /* raise inexact flag */ u.bits.manh &= ~m; u.bits.manl = 0; } } } else if (e < LDBL_MANT_DIG - 1) { uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); if ((u.bits.manl & m) == 0) return (x); /* x is integral */ if (!u.bits.sign) { if (e == MANH_SIZE - 1) INC_MANH(u, 1); else { uint64_t o = u.bits.manl; u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1); if (u.bits.manl < o) /* got a carry */ INC_MANH(u, 1); } } if (huge + x > 0.0) /* raise inexact flag */ u.bits.manl &= ~m; } return (u.e); } diff --git a/lib/msun/src/s_cexp.c b/lib/msun/src/s_cexp.c index 056d273f6932..0151768473c7 100644 --- a/lib/msun/src/s_cexp.c +++ b/lib/msun/src/s_cexp.c @@ -1,97 +1,96 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "math_private.h" static const uint32_t exp_ovfl = 0x40862e42, /* high bits of MAX_EXP * ln2 ~= 710 */ cexp_ovfl = 0x4096b8e4; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */ double complex cexp(double complex z) { double c, exp_x, s, x, y; uint32_t hx, hy, lx, ly; x = creal(z); y = cimag(z); EXTRACT_WORDS(hy, ly, y); hy &= 0x7fffffff; /* cexp(x + I 0) = exp(x) + I 0 */ if ((hy | ly) == 0) return (CMPLX(exp(x), y)); EXTRACT_WORDS(hx, lx, x); /* cexp(0 + I y) = cos(y) + I sin(y) */ if (((hx & 0x7fffffff) | lx) == 0) { sincos(y, &s, &c); return (CMPLX(c, s)); } if (hy >= 0x7ff00000) { if (lx != 0 || (hx & 0x7fffffff) != 0x7ff00000) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ return (CMPLX(y - y, y - y)); } else if (hx & 0x80000000) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ return (CMPLX(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ return (CMPLX(x, y - y)); } } if (hx >= exp_ovfl && hx <= cexp_ovfl) { /* * x is between 709.7 and 1454.3, so we must scale to avoid * overflow in exp(x). */ return (__ldexp_cexp(z, 0)); } else { /* * Cases covered here: * - x < exp_ovfl and exp(x) won't overflow (common case) * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 * - x = +-Inf (generated by exp()) * - x = NaN (spurious inexact exception from y) */ exp_x = exp(x); sincos(y, &s, &c); return (CMPLX(exp_x * c, exp_x * s)); } } #if (LDBL_MANT_DIG == 53) __weak_reference(cexp, cexpl); #endif diff --git a/lib/msun/src/s_cexpf.c b/lib/msun/src/s_cexpf.c index 872e9253daa5..a6c0c995cf5e 100644 --- a/lib/msun/src/s_cexpf.c +++ b/lib/msun/src/s_cexpf.c @@ -1,92 +1,91 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "math_private.h" static const uint32_t exp_ovfl = 0x42b17218, /* MAX_EXP * ln2 ~= 88.722839355 */ cexp_ovfl = 0x43400074; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */ float complex cexpf(float complex z) { float c, exp_x, s, x, y; uint32_t hx, hy; x = crealf(z); y = cimagf(z); GET_FLOAT_WORD(hy, y); hy &= 0x7fffffff; /* cexp(x + I 0) = exp(x) + I 0 */ if (hy == 0) return (CMPLXF(expf(x), y)); GET_FLOAT_WORD(hx, x); /* cexp(0 + I y) = cos(y) + I sin(y) */ if ((hx & 0x7fffffff) == 0) { sincosf(y, &s, &c); return (CMPLXF(c, s)); } if (hy >= 0x7f800000) { if ((hx & 0x7fffffff) != 0x7f800000) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ return (CMPLXF(y - y, y - y)); } else if (hx & 0x80000000) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ return (CMPLXF(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ return (CMPLXF(x, y - y)); } } if (hx >= exp_ovfl && hx <= cexp_ovfl) { /* * x is between 88.7 and 192, so we must scale to avoid * overflow in expf(x). */ return (__ldexp_cexpf(z, 0)); } else { /* * Cases covered here: * - x < exp_ovfl and exp(x) won't overflow (common case) * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0 * - x = +-Inf (generated by exp()) * - x = NaN (spurious inexact exception from y) */ exp_x = expf(x); sincosf(y, &s, &c); return (CMPLXF(exp_x * c, exp_x * s)); } } diff --git a/lib/msun/src/s_clog.c b/lib/msun/src/s_clog.c index e51ff5230e45..2129890f43de 100644 --- a/lib/msun/src/s_clog.c +++ b/lib/msun/src/s_clog.c @@ -1,153 +1,152 @@ /*- * Copyright (c) 2013 Bruce D. Evans * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define MANT_DIG DBL_MANT_DIG #define MAX_EXP DBL_MAX_EXP #define MIN_EXP DBL_MIN_EXP static const double ln2_hi = 6.9314718055829871e-1, /* 0x162e42fefa0000.0p-53 */ ln2_lo = 1.6465949582897082e-12; /* 0x1cf79abc9e3b3a.0p-92 */ double complex clog(double complex z) { double_t ax, ax2h, ax2l, axh, axl, ay, ay2h, ay2l, ayh, ayl, sh, sl, t; double x, y, v; uint32_t hax, hay; int kx, ky; x = creal(z); y = cimag(z); v = atan2(y, x); ax = fabs(x); ay = fabs(y); if (ax < ay) { t = ax; ax = ay; ay = t; } GET_HIGH_WORD(hax, ax); kx = (hax >> 20) - 1023; GET_HIGH_WORD(hay, ay); ky = (hay >> 20) - 1023; /* Handle NaNs and Infs using the general formula. */ if (kx == MAX_EXP || ky == MAX_EXP) return (CMPLX(log(hypot(x, y)), v)); /* Avoid spurious underflow, and reduce inaccuracies when ax is 1. */ if (ax == 1) { if (ky < (MIN_EXP - 1) / 2) return (CMPLX((ay / 2) * ay, v)); return (CMPLX(log1p(ay * ay) / 2, v)); } /* Avoid underflow when ax is not small. Also handle zero args. */ if (kx - ky > MANT_DIG || ay == 0) return (CMPLX(log(ax), v)); /* Avoid overflow. */ if (kx >= MAX_EXP - 1) return (CMPLX(log(hypot(x * 0x1p-1022, y * 0x1p-1022)) + (MAX_EXP - 2) * ln2_lo + (MAX_EXP - 2) * ln2_hi, v)); if (kx >= (MAX_EXP - 1) / 2) return (CMPLX(log(hypot(x, y)), v)); /* Reduce inaccuracies and avoid underflow when ax is denormal. */ if (kx <= MIN_EXP - 2) return (CMPLX(log(hypot(x * 0x1p1023, y * 0x1p1023)) + (MIN_EXP - 2) * ln2_lo + (MIN_EXP - 2) * ln2_hi, v)); /* Avoid remaining underflows (when ax is small but not denormal). */ if (ky < (MIN_EXP - 1) / 2 + MANT_DIG) return (CMPLX(log(hypot(x, y)), v)); /* Calculate ax*ax and ay*ay exactly using Dekker's algorithm. */ t = (double)(ax * (0x1p27 + 1)); axh = (double)(ax - t) + t; axl = ax - axh; ax2h = ax * ax; ax2l = axh * axh - ax2h + 2 * axh * axl + axl * axl; t = (double)(ay * (0x1p27 + 1)); ayh = (double)(ay - t) + t; ayl = ay - ayh; ay2h = ay * ay; ay2l = ayh * ayh - ay2h + 2 * ayh * ayl + ayl * ayl; /* * When log(|z|) is far from 1, accuracy in calculating the sum * of the squares is not very important since log() reduces * inaccuracies. We depended on this to use the general * formula when log(|z|) is very far from 1. When log(|z|) is * moderately far from 1, we go through the extra-precision * calculations to reduce branches and gain a little accuracy. * * When |z| is near 1, we subtract 1 and use log1p() and don't * leave it to log() to subtract 1, since we gain at least 1 bit * of accuracy in this way. * * When |z| is very near 1, subtracting 1 can cancel almost * 3*MANT_DIG bits. We arrange that subtracting 1 is exact in * doubled precision, and then do the rest of the calculation * in sloppy doubled precision. Although large cancellations * often lose lots of accuracy, here the final result is exact * in doubled precision if the large calculation occurs (because * then it is exact in tripled precision and the cancellation * removes enough bits to fit in doubled precision). Thus the * result is accurate in sloppy doubled precision, and the only * significant loss of accuracy is when it is summed and passed * to log1p(). */ sh = ax2h; sl = ay2h; _2sumF(sh, sl); if (sh < 0.5 || sh >= 3) return (CMPLX(log(ay2l + ax2l + sl + sh) / 2, v)); sh -= 1; _2sum(sh, sl); _2sum(ax2l, ay2l); /* Briggs-Kahan algorithm (except we discard the final low term): */ _2sum(sh, ax2l); _2sum(sl, ay2l); t = ax2l + sl; _2sumF(sh, t); return (CMPLX(log1p(ay2l + t + sh) / 2, v)); } #if (LDBL_MANT_DIG == 53) __weak_reference(clog, clogl); #endif diff --git a/lib/msun/src/s_clogf.c b/lib/msun/src/s_clogf.c index 761f91b12efa..2204e1e59bb6 100644 --- a/lib/msun/src/s_clogf.c +++ b/lib/msun/src/s_clogf.c @@ -1,149 +1,148 @@ /*- * Copyright (c) 2013 Bruce D. Evans * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define MANT_DIG FLT_MANT_DIG #define MAX_EXP FLT_MAX_EXP #define MIN_EXP FLT_MIN_EXP static const float ln2f_hi = 6.9314575195e-1, /* 0xb17200.0p-24 */ ln2f_lo = 1.4286067653e-6; /* 0xbfbe8e.0p-43 */ float complex clogf(float complex z) { float_t ax, ax2h, ax2l, axh, axl, ay, ay2h, ay2l, ayh, ayl, sh, sl, t; float x, y, v; uint32_t hax, hay; int kx, ky; x = crealf(z); y = cimagf(z); v = atan2f(y, x); ax = fabsf(x); ay = fabsf(y); if (ax < ay) { t = ax; ax = ay; ay = t; } GET_FLOAT_WORD(hax, ax); kx = (hax >> 23) - 127; GET_FLOAT_WORD(hay, ay); ky = (hay >> 23) - 127; /* Handle NaNs and Infs using the general formula. */ if (kx == MAX_EXP || ky == MAX_EXP) return (CMPLXF(logf(hypotf(x, y)), v)); /* Avoid spurious underflow, and reduce inaccuracies when ax is 1. */ if (hax == 0x3f800000) { if (ky < (MIN_EXP - 1) / 2) return (CMPLXF((ay / 2) * ay, v)); return (CMPLXF(log1pf(ay * ay) / 2, v)); } /* Avoid underflow when ax is not small. Also handle zero args. */ if (kx - ky > MANT_DIG || hay == 0) return (CMPLXF(logf(ax), v)); /* Avoid overflow. */ if (kx >= MAX_EXP - 1) return (CMPLXF(logf(hypotf(x * 0x1p-126F, y * 0x1p-126F)) + (MAX_EXP - 2) * ln2f_lo + (MAX_EXP - 2) * ln2f_hi, v)); if (kx >= (MAX_EXP - 1) / 2) return (CMPLXF(logf(hypotf(x, y)), v)); /* Reduce inaccuracies and avoid underflow when ax is denormal. */ if (kx <= MIN_EXP - 2) return (CMPLXF(logf(hypotf(x * 0x1p127F, y * 0x1p127F)) + (MIN_EXP - 2) * ln2f_lo + (MIN_EXP - 2) * ln2f_hi, v)); /* Avoid remaining underflows (when ax is small but not denormal). */ if (ky < (MIN_EXP - 1) / 2 + MANT_DIG) return (CMPLXF(logf(hypotf(x, y)), v)); /* Calculate ax*ax and ay*ay exactly using Dekker's algorithm. */ t = (float)(ax * (0x1p12F + 1)); axh = (float)(ax - t) + t; axl = ax - axh; ax2h = ax * ax; ax2l = axh * axh - ax2h + 2 * axh * axl + axl * axl; t = (float)(ay * (0x1p12F + 1)); ayh = (float)(ay - t) + t; ayl = ay - ayh; ay2h = ay * ay; ay2l = ayh * ayh - ay2h + 2 * ayh * ayl + ayl * ayl; /* * When log(|z|) is far from 1, accuracy in calculating the sum * of the squares is not very important since log() reduces * inaccuracies. We depended on this to use the general * formula when log(|z|) is very far from 1. When log(|z|) is * moderately far from 1, we go through the extra-precision * calculations to reduce branches and gain a little accuracy. * * When |z| is near 1, we subtract 1 and use log1p() and don't * leave it to log() to subtract 1, since we gain at least 1 bit * of accuracy in this way. * * When |z| is very near 1, subtracting 1 can cancel almost * 3*MANT_DIG bits. We arrange that subtracting 1 is exact in * doubled precision, and then do the rest of the calculation * in sloppy doubled precision. Although large cancellations * often lose lots of accuracy, here the final result is exact * in doubled precision if the large calculation occurs (because * then it is exact in tripled precision and the cancellation * removes enough bits to fit in doubled precision). Thus the * result is accurate in sloppy doubled precision, and the only * significant loss of accuracy is when it is summed and passed * to log1p(). */ sh = ax2h; sl = ay2h; _2sumF(sh, sl); if (sh < 0.5F || sh >= 3) return (CMPLXF(logf(ay2l + ax2l + sl + sh) / 2, v)); sh -= 1; _2sum(sh, sl); _2sum(ax2l, ay2l); /* Briggs-Kahan algorithm (except we discard the final low term): */ _2sum(sh, ax2l); _2sum(sl, ay2l); t = ax2l + sl; _2sumF(sh, t); return (CMPLXF(log1pf(ay2l + t + sh) / 2, v)); } diff --git a/lib/msun/src/s_clogl.c b/lib/msun/src/s_clogl.c index 78244961df5c..075bdb49f851 100644 --- a/lib/msun/src/s_clogl.c +++ b/lib/msun/src/s_clogl.c @@ -1,166 +1,165 @@ /*- * Copyright (c) 2013 Bruce D. Evans * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #define MANT_DIG LDBL_MANT_DIG #define MAX_EXP LDBL_MAX_EXP #define MIN_EXP LDBL_MIN_EXP static const double ln2_hi = 6.9314718055829871e-1; /* 0x162e42fefa0000.0p-53 */ #if LDBL_MANT_DIG == 64 #define MULT_REDUX 0x1p32 /* exponent MANT_DIG / 2 rounded up */ static const double ln2l_lo = 1.6465949582897082e-12; /* 0x1cf79abc9e3b3a.0p-92 */ #elif LDBL_MANT_DIG == 113 #define MULT_REDUX 0x1p57 static const long double ln2l_lo = 1.64659495828970812809844307550013433e-12L; /* 0x1cf79abc9e3b39803f2f6af40f343.0p-152L */ #else #error "Unsupported long double format" #endif long double complex clogl(long double complex z) { long double ax, ax2h, ax2l, axh, axl, ay, ay2h, ay2l, ayh, ayl; long double sh, sl, t; long double x, y, v; uint16_t hax, hay; int kx, ky; ENTERIT(long double complex); x = creall(z); y = cimagl(z); v = atan2l(y, x); ax = fabsl(x); ay = fabsl(y); if (ax < ay) { t = ax; ax = ay; ay = t; } GET_LDBL_EXPSIGN(hax, ax); kx = hax - 16383; GET_LDBL_EXPSIGN(hay, ay); ky = hay - 16383; /* Handle NaNs and Infs using the general formula. */ if (kx == MAX_EXP || ky == MAX_EXP) RETURNI(CMPLXL(logl(hypotl(x, y)), v)); /* Avoid spurious underflow, and reduce inaccuracies when ax is 1. */ if (ax == 1) { if (ky < (MIN_EXP - 1) / 2) RETURNI(CMPLXL((ay / 2) * ay, v)); RETURNI(CMPLXL(log1pl(ay * ay) / 2, v)); } /* Avoid underflow when ax is not small. Also handle zero args. */ if (kx - ky > MANT_DIG || ay == 0) RETURNI(CMPLXL(logl(ax), v)); /* Avoid overflow. */ if (kx >= MAX_EXP - 1) RETURNI(CMPLXL(logl(hypotl(x * 0x1p-16382L, y * 0x1p-16382L)) + (MAX_EXP - 2) * ln2l_lo + (MAX_EXP - 2) * ln2_hi, v)); if (kx >= (MAX_EXP - 1) / 2) RETURNI(CMPLXL(logl(hypotl(x, y)), v)); /* Reduce inaccuracies and avoid underflow when ax is denormal. */ if (kx <= MIN_EXP - 2) RETURNI(CMPLXL(logl(hypotl(x * 0x1p16383L, y * 0x1p16383L)) + (MIN_EXP - 2) * ln2l_lo + (MIN_EXP - 2) * ln2_hi, v)); /* Avoid remaining underflows (when ax is small but not denormal). */ if (ky < (MIN_EXP - 1) / 2 + MANT_DIG) RETURNI(CMPLXL(logl(hypotl(x, y)), v)); /* Calculate ax*ax and ay*ay exactly using Dekker's algorithm. */ t = (long double)(ax * (MULT_REDUX + 1)); axh = (long double)(ax - t) + t; axl = ax - axh; ax2h = ax * ax; ax2l = axh * axh - ax2h + 2 * axh * axl + axl * axl; t = (long double)(ay * (MULT_REDUX + 1)); ayh = (long double)(ay - t) + t; ayl = ay - ayh; ay2h = ay * ay; ay2l = ayh * ayh - ay2h + 2 * ayh * ayl + ayl * ayl; /* * When log(|z|) is far from 1, accuracy in calculating the sum * of the squares is not very important since log() reduces * inaccuracies. We depended on this to use the general * formula when log(|z|) is very far from 1. When log(|z|) is * moderately far from 1, we go through the extra-precision * calculations to reduce branches and gain a little accuracy. * * When |z| is near 1, we subtract 1 and use log1p() and don't * leave it to log() to subtract 1, since we gain at least 1 bit * of accuracy in this way. * * When |z| is very near 1, subtracting 1 can cancel almost * 3*MANT_DIG bits. We arrange that subtracting 1 is exact in * doubled precision, and then do the rest of the calculation * in sloppy doubled precision. Although large cancellations * often lose lots of accuracy, here the final result is exact * in doubled precision if the large calculation occurs (because * then it is exact in tripled precision and the cancellation * removes enough bits to fit in doubled precision). Thus the * result is accurate in sloppy doubled precision, and the only * significant loss of accuracy is when it is summed and passed * to log1p(). */ sh = ax2h; sl = ay2h; _2sumF(sh, sl); if (sh < 0.5 || sh >= 3) RETURNI(CMPLXL(logl(ay2l + ax2l + sl + sh) / 2, v)); sh -= 1; _2sum(sh, sl); _2sum(ax2l, ay2l); /* Briggs-Kahan algorithm (except we discard the final low term): */ _2sum(sh, ax2l); _2sum(sl, ay2l); t = ax2l + sl; _2sumF(sh, t); RETURNI(CMPLXL(log1pl(ay2l + t + sh) / 2, v)); } diff --git a/lib/msun/src/s_copysign.c b/lib/msun/src/s_copysign.c index 2a9923a2480a..21a39839deea 100644 --- a/lib/msun/src/s_copysign.c +++ b/lib/msun/src/s_copysign.c @@ -1,31 +1,30 @@ /* @(#)s_copysign.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * copysign(double x, double y) * copysign(x,y) returns a value with the magnitude of x and * with the sign bit of y. */ #include "math.h" #include "math_private.h" double copysign(double x, double y) { u_int32_t hx,hy; GET_HIGH_WORD(hx,x); GET_HIGH_WORD(hy,y); SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); return x; } diff --git a/lib/msun/src/s_copysignf.c b/lib/msun/src/s_copysignf.c index a35b07ccbb5b..68964e509b6c 100644 --- a/lib/msun/src/s_copysignf.c +++ b/lib/msun/src/s_copysignf.c @@ -1,34 +1,33 @@ /* s_copysignf.c -- float version of s_copysign.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * copysignf(float x, float y) * copysignf(x,y) returns a value with the magnitude of x and * with the sign bit of y. */ #include "math.h" #include "math_private.h" float copysignf(float x, float y) { u_int32_t ix,iy; GET_FLOAT_WORD(ix,x); GET_FLOAT_WORD(iy,y); SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000)); return x; } diff --git a/lib/msun/src/s_cos.c b/lib/msun/src/s_cos.c index 97f72a15ce4d..6c5510008f8c 100644 --- a/lib/msun/src/s_cos.c +++ b/lib/msun/src/s_cos.c @@ -1,87 +1,86 @@ /* @(#)s_cos.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* cos(x) * Return cosine function of x. * * kernel function: * __kernel_sin ... sine function on [-pi/4,pi/4] * __kernel_cos ... cosine function on [-pi/4,pi/4] * __ieee754_rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include #include "math.h" #define INLINE_REM_PIO2 #include "math_private.h" #include "e_rem_pio2.c" double cos(double x) { double y[2],z=0.0; int32_t n, ix; /* High word of x. */ GET_HIGH_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) { if(ix<0x3e46a09e) /* if x < 2**-27 * sqrt(2) */ if(((int)x)==0) return 1.0; /* generate inexact */ return __kernel_cos(x,z); } /* cos(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); switch(n&3) { case 0: return __kernel_cos(y[0],y[1]); case 1: return -__kernel_sin(y[0],y[1],1); case 2: return -__kernel_cos(y[0],y[1]); default: return __kernel_sin(y[0],y[1],1); } } } #if (LDBL_MANT_DIG == 53) __weak_reference(cos, cosl); #endif diff --git a/lib/msun/src/s_cosf.c b/lib/msun/src/s_cosf.c index a0ba8598f7e6..6fc53f7b874f 100644 --- a/lib/msun/src/s_cosf.c +++ b/lib/msun/src/s_cosf.c @@ -1,85 +1,84 @@ /* s_cosf.c -- float version of s_cos.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #define INLINE_KERNEL_COSDF #define INLINE_KERNEL_SINDF #define INLINE_REM_PIO2F #include "math_private.h" #include "e_rem_pio2f.c" #include "k_cosf.c" #include "k_sinf.c" /* Small multiples of pi/2 rounded to double precision. */ static const double c1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ c2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ c3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ c4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ float cosf(float x) { double y; int32_t n, hx, ix; GET_FLOAT_WORD(hx,x); ix = hx & 0x7fffffff; if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ if(ix<0x39800000) /* |x| < 2**-12 */ if(((int)x)==0) return 1.0; /* 1 with inexact if x != 0 */ return __kernel_cosdf(x); } if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */ if(ix>0x4016cbe3) /* |x| ~> 3*pi/4 */ return -__kernel_cosdf(x + (hx > 0 ? -c2pio2 : c2pio2)); else { if(hx>0) return __kernel_sindf(c1pio2 - x); else return __kernel_sindf(x + c1pio2); } } if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */ if(ix>0x40afeddf) /* |x| ~> 7*pi/4 */ return __kernel_cosdf(x + (hx > 0 ? -c4pio2 : c4pio2)); else { if(hx>0) return __kernel_sindf(x - c3pio2); else return __kernel_sindf(-c3pio2 - x); } } /* cos(Inf or NaN) is NaN */ else if (ix>=0x7f800000) return x-x; /* general argument reduction needed */ else { n = __ieee754_rem_pio2f(x,&y); switch(n&3) { case 0: return __kernel_cosdf(y); case 1: return __kernel_sindf(-y); case 2: return -__kernel_cosdf(y); default: return __kernel_sindf(y); } } } diff --git a/lib/msun/src/s_cosl.c b/lib/msun/src/s_cosl.c index 00c24ce13d12..32fc8b26a206 100644 --- a/lib/msun/src/s_cosl.c +++ b/lib/msun/src/s_cosl.c @@ -1,100 +1,99 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include /* * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows * an accuracy of <= 0.7412 ULP. */ #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" #if LDBL_MANT_DIG == 64 #include "../ld80/e_rem_pio2l.h" static const union IEEEl2bits pio4u = LD80C(0xc90fdaa22168c235, -00001, 7.85398163397448309628e-01L); #define pio4 (pio4u.e) #elif LDBL_MANT_DIG == 113 #include "../ld128/e_rem_pio2l.h" long double pio4 = 7.85398163397448309615660845819875721e-1L; #else #error "Unsupported long double format" #endif long double cosl(long double x) { union IEEEl2bits z; int e0; long double y[2]; long double hi, lo; z.e = x; z.bits.sign = 0; /* If x = +-0 or x is a subnormal number, then cos(x) = 1 */ if (z.bits.exp == 0) return (1.0); /* If x = NaN or Inf, then cos(x) = NaN. */ if (z.bits.exp == 32767) return ((x - x) / (x - x)); ENTERI(); /* Optimize the case where x is already within range. */ if (z.e < pio4) RETURNI(__kernel_cosl(z.e, 0)); e0 = __ieee754_rem_pio2l(x, y); hi = y[0]; lo = y[1]; switch (e0 & 3) { case 0: hi = __kernel_cosl(hi, lo); break; case 1: hi = - __kernel_sinl(hi, lo, 1); break; case 2: hi = - __kernel_cosl(hi, lo); break; case 3: hi = __kernel_sinl(hi, lo, 1); break; } RETURNI(hi); } diff --git a/lib/msun/src/s_cpow.c b/lib/msun/src/s_cpow.c index 735d38956380..b887db51aa2a 100644 --- a/lib/msun/src/s_cpow.c +++ b/lib/msun/src/s_cpow.c @@ -1,73 +1,72 @@ /*- * Copyright (c) 2008 Stephen L. Moshier * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* cpow * * Complex power function * * * * SYNOPSIS: * * double complex cpow(); * double complex a, z, w; * * w = cpow (a, z); * * * * DESCRIPTION: * * Raises complex A to the complex Zth power. * Definition is per AMS55 # 4.2.8, * analytically equivalent to cpow(a,z) = cexp(z clog(a)). * * ACCURACY: * * Relative error: * arithmetic domain # trials peak rms * IEEE -10,+10 30000 9.4e-15 1.5e-15 * */ -#include #include #include #include #include "math_private.h" double complex cpow(double complex a, double complex z) { double complex w; double x, y, r, theta, absa, arga; x = creal (z); y = cimag (z); absa = cabs (a); if (absa == 0.0) { return (CMPLX(0.0, 0.0)); } arga = carg (a); r = pow (absa, x); theta = x * arga; if (y != 0.0) { r = r * exp (-y * arga); theta = theta + y * log (absa); } w = CMPLX(r * cos (theta), r * sin (theta)); return (w); } diff --git a/lib/msun/src/s_cpowf.c b/lib/msun/src/s_cpowf.c index aefcd7619de1..144291079f97 100644 --- a/lib/msun/src/s_cpowf.c +++ b/lib/msun/src/s_cpowf.c @@ -1,72 +1,71 @@ /*- * Copyright (c) 2008 Stephen L. Moshier * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* cpowf * * Complex power function * * * * SYNOPSIS: * * float complex cpowf(); * float complex a, z, w; * * w = cpowf (a, z); * * * * DESCRIPTION: * * Raises complex A to the complex Zth power. * Definition is per AMS55 # 4.2.8, * analytically equivalent to cpow(a,z) = cexp(z clog(a)). * * ACCURACY: * * Relative error: * arithmetic domain # trials peak rms * IEEE -10,+10 30000 9.4e-15 1.5e-15 * */ -#include #include #include #include "math_private.h" float complex cpowf(float complex a, float complex z) { float complex w; float x, y, r, theta, absa, arga; x = crealf(z); y = cimagf(z); absa = cabsf (a); if (absa == 0.0f) { return (CMPLXF(0.0f, 0.0f)); } arga = cargf (a); r = powf (absa, x); theta = x * arga; if (y != 0.0f) { r = r * expf (-y * arga); theta = theta + y * logf (absa); } w = CMPLXF(r * cosf (theta), r * sinf (theta)); return (w); } diff --git a/lib/msun/src/s_cpowl.c b/lib/msun/src/s_cpowl.c index 342dfcff8481..39797cadcfcb 100644 --- a/lib/msun/src/s_cpowl.c +++ b/lib/msun/src/s_cpowl.c @@ -1,72 +1,71 @@ /*- * Copyright (c) 2008 Stephen L. Moshier * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* cpowl * * Complex power function * * * * SYNOPSIS: * * long double complex cpowl(); * long double complex a, z, w; * * w = cpowl (a, z); * * * * DESCRIPTION: * * Raises complex A to the complex Zth power. * Definition is per AMS55 # 4.2.8, * analytically equivalent to cpow(a,z) = cexp(z clog(a)). * * ACCURACY: * * Relative error: * arithmetic domain # trials peak rms * IEEE -10,+10 30000 9.4e-15 1.5e-15 * */ -#include #include #include #include "math_private.h" long double complex cpowl(long double complex a, long double complex z) { long double complex w; long double x, y, r, theta, absa, arga; x = creall(z); y = cimagl(z); absa = cabsl(a); if (absa == 0.0L) { return (CMPLXL(0.0L, 0.0L)); } arga = cargl(a); r = powl(absa, x); theta = x * arga; if (y != 0.0L) { r = r * expl(-y * arga); theta = theta + y * logl(absa); } w = CMPLXL(r * cosl(theta), r * sinl(theta)); return (w); } diff --git a/lib/msun/src/s_cproj.c b/lib/msun/src/s_cproj.c index 75cb083baf17..9eebb450ae11 100644 --- a/lib/msun/src/s_cproj.c +++ b/lib/msun/src/s_cproj.c @@ -1,48 +1,47 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "math_private.h" double complex cproj(double complex z) { if (!isinf(creal(z)) && !isinf(cimag(z))) return (z); else return (CMPLX(INFINITY, copysign(0.0, cimag(z)))); } #if LDBL_MANT_DIG == 53 __weak_reference(cproj, cprojl); #endif diff --git a/lib/msun/src/s_cprojf.c b/lib/msun/src/s_cprojf.c index aadc5ef35cbd..13d90ba6fb5e 100644 --- a/lib/msun/src/s_cprojf.c +++ b/lib/msun/src/s_cprojf.c @@ -1,43 +1,42 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "math_private.h" float complex cprojf(float complex z) { if (!isinf(crealf(z)) && !isinf(cimagf(z))) return (z); else return (CMPLXF(INFINITY, copysignf(0.0, cimagf(z)))); } diff --git a/lib/msun/src/s_cprojl.c b/lib/msun/src/s_cprojl.c index 78e3e9a6fdca..083b5fa1c8f3 100644 --- a/lib/msun/src/s_cprojl.c +++ b/lib/msun/src/s_cprojl.c @@ -1,43 +1,42 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "math_private.h" long double complex cprojl(long double complex z) { if (!isinf(creall(z)) && !isinf(cimagl(z))) return (z); else return (CMPLXL(INFINITY, copysignl(0.0, cimagl(z)))); } diff --git a/lib/msun/src/s_csinh.c b/lib/msun/src/s_csinh.c index 1bd78b1e49bf..e7ed10e7d885 100644 --- a/lib/msun/src/s_csinh.c +++ b/lib/msun/src/s_csinh.c @@ -1,157 +1,156 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Hyperbolic sine of a complex argument z = x + i y. * * sinh(z) = sinh(x+iy) * = sinh(x) cos(y) + i cosh(x) sin(y). * * Exceptional values are noted in the comments within the source code. * These values and the return value were taken from n1124.pdf. * The sign of the result for some exceptional values is unspecified but * must satisfy both sinh(conj(z)) == conj(sinh(z)) and sinh(-z) == -sinh(z). */ -#include #include #include #include "math_private.h" static const double huge = 0x1p1023; double complex csinh(double complex z) { double x, y, h; int32_t hx, hy, ix, iy, lx, ly; x = creal(z); y = cimag(z); EXTRACT_WORDS(hx, lx, x); EXTRACT_WORDS(hy, ly, y); ix = 0x7fffffff & hx; iy = 0x7fffffff & hy; /* Handle the nearly-non-exceptional cases where x and y are finite. */ if (ix < 0x7ff00000 && iy < 0x7ff00000) { if ((iy | ly) == 0) return (CMPLX(sinh(x), y)); if (ix < 0x40360000) /* |x| < 22: normal case */ return (CMPLX(sinh(x) * cos(y), cosh(x) * sin(y))); /* |x| >= 22, so cosh(x) ~= exp(|x|) */ if (ix < 0x40862e42) { /* x < 710: exp(|x|) won't overflow */ h = exp(fabs(x)) * 0.5; return (CMPLX(copysign(h, x) * cos(y), h * sin(y))); } else if (ix < 0x4096bbaa) { /* x < 1455: scale to avoid overflow */ z = __ldexp_cexp(CMPLX(fabs(x), y), -1); return (CMPLX(creal(z) * copysign(1, x), cimag(z))); } else { /* x >= 1455: the result always overflows */ h = huge * x; return (CMPLX(h * cos(y), h * h * sin(y))); } } /* * sinh(+-0 +- I Inf) = +-0 + I dNaN. * The sign of 0 in the result is unspecified. Choice = same sign * as the argument. Raise the invalid floating-point exception. * * sinh(+-0 +- I NaN) = +-0 + I d(NaN). * The sign of 0 in the result is unspecified. Choice = same sign * as the argument. */ if ((ix | lx) == 0) /* && iy >= 0x7ff00000 */ return (CMPLX(x, y - y)); /* * sinh(+-Inf +- I 0) = +-Inf + I +-0. * * sinh(NaN +- I 0) = d(NaN) + I +-0. */ if ((iy | ly) == 0) /* && ix >= 0x7ff00000 */ return (CMPLX(x + x, y)); /* * sinh(x +- I Inf) = dNaN + I dNaN. * Raise the invalid floating-point exception for finite nonzero x. * * sinh(x + I NaN) = d(NaN) + I d(NaN). * Optionally raises the invalid floating-point exception for finite * nonzero x. Choice = don't raise (except for signaling NaNs). */ if (ix < 0x7ff00000) /* && iy >= 0x7ff00000 */ return (CMPLX(y - y, y - y)); /* * sinh(+-Inf + I NaN) = +-Inf + I d(NaN). * The sign of Inf in the result is unspecified. Choice = same sign * as the argument. * * sinh(+-Inf +- I Inf) = +-Inf + I dNaN. * The sign of Inf in the result is unspecified. Choice = same sign * as the argument. Raise the invalid floating-point exception. * * sinh(+-Inf + I y) = +-Inf cos(y) + I Inf sin(y) */ if (ix == 0x7ff00000 && lx == 0) { if (iy >= 0x7ff00000) return (CMPLX(x, y - y)); return (CMPLX(x * cos(y), INFINITY * sin(y))); } /* * sinh(NaN1 + I NaN2) = d(NaN1, NaN2) + I d(NaN1, NaN2). * * sinh(NaN +- I Inf) = d(NaN, dNaN) + I d(NaN, dNaN). * Optionally raises the invalid floating-point exception. * Choice = raise. * * sinh(NaN + I y) = d(NaN) + I d(NaN). * Optionally raises the invalid floating-point exception for finite * nonzero y. Choice = don't raise (except for signaling NaNs). */ return (CMPLX(((long double)x + x) * (y - y), ((long double)x * x) * (y - y))); } double complex csin(double complex z) { /* csin(z) = -I * csinh(I * z) = I * conj(csinh(I * conj(z))). */ z = csinh(CMPLX(cimag(z), creal(z))); return (CMPLX(cimag(z), creal(z))); } diff --git a/lib/msun/src/s_csinhf.c b/lib/msun/src/s_csinhf.c index b1f333955e53..c4392755c482 100644 --- a/lib/msun/src/s_csinhf.c +++ b/lib/msun/src/s_csinhf.c @@ -1,103 +1,102 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Float version of csinh(). See s_csinh.c for details. */ -#include #include #include #include "math_private.h" static const float huge = 0x1p127; float complex csinhf(float complex z) { float x, y, h; int32_t hx, hy, ix, iy; x = crealf(z); y = cimagf(z); GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = 0x7fffffff & hx; iy = 0x7fffffff & hy; if (ix < 0x7f800000 && iy < 0x7f800000) { if (iy == 0) return (CMPLXF(sinhf(x), y)); if (ix < 0x41100000) /* |x| < 9: normal case */ return (CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y))); /* |x| >= 9, so cosh(x) ~= exp(|x|) */ if (ix < 0x42b17218) { /* x < 88.7: expf(|x|) won't overflow */ h = expf(fabsf(x)) * 0.5F; return (CMPLXF(copysignf(h, x) * cosf(y), h * sinf(y))); } else if (ix < 0x4340b1e7) { /* x < 192.7: scale to avoid overflow */ z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); return (CMPLXF(crealf(z) * copysignf(1, x), cimagf(z))); } else { /* x >= 192.7: the result always overflows */ h = huge * x; return (CMPLXF(h * cosf(y), h * h * sinf(y))); } } if (ix == 0) /* && iy >= 0x7f800000 */ return (CMPLXF(x, y - y)); if (iy == 0) /* && ix >= 0x7f800000 */ return (CMPLXF(x + x, y)); if (ix < 0x7f800000) /* && iy >= 0x7f800000 */ return (CMPLXF(y - y, y - y)); if (ix == 0x7f800000) { if (iy >= 0x7f800000) return (CMPLXF(x, y - y)); return (CMPLXF(x * cosf(y), INFINITY * sinf(y))); } return (CMPLXF(((long double)x + x) * (y - y), ((long double)x * x) * (y - y))); } float complex csinf(float complex z) { z = csinhf(CMPLXF(cimagf(z), crealf(z))); return (CMPLXF(cimagf(z), crealf(z))); } diff --git a/lib/msun/src/s_csqrt.c b/lib/msun/src/s_csqrt.c index afac4db17b61..c40b5a6de907 100644 --- a/lib/msun/src/s_csqrt.c +++ b/lib/msun/src/s_csqrt.c @@ -1,113 +1,112 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "math_private.h" /* For avoiding overflow for components >= DBL_MAX / (1 + sqrt(2)). */ #define THRESH 0x1.a827999fcef32p+1022 double complex csqrt(double complex z) { double complex result; double a, b, rx, ry, scale, t; a = creal(z); b = cimag(z); /* Handle special cases. */ if (z == 0) return (CMPLX(0, b)); if (isinf(b)) return (CMPLX(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ return (CMPLX(a + 0.0L + t, a + 0.0L + t)); /* NaN + NaN i */ } if (isinf(a)) { /* * csqrt(inf + NaN i) = inf + NaN i * csqrt(inf + y i) = inf + 0 i * csqrt(-inf + NaN i) = NaN +- inf i * csqrt(-inf + y i) = 0 + inf i */ if (signbit(a)) return (CMPLX(fabs(b - b), copysign(a, b))); else return (CMPLX(a, copysign(b - b, b))); } if (isnan(b)) { t = (a - a) / (a - a); /* raise invalid */ return (CMPLX(b + 0.0L + t, b + 0.0L + t)); /* NaN + NaN i */ } /* Scale to avoid overflow. */ if (fabs(a) >= THRESH || fabs(b) >= THRESH) { /* * Don't scale a or b if this might give (spurious) * underflow. Then the unscaled value is an equivalent * infinitesmal (or 0). */ if (fabs(a) >= 0x1p-1020) a *= 0.25; if (fabs(b) >= 0x1p-1020) b *= 0.25; scale = 2; } else { scale = 1; } /* Scale to reduce inaccuracies when both components are denormal. */ if (fabs(a) < 0x1p-1022 && fabs(b) < 0x1p-1022) { a *= 0x1p54; b *= 0x1p54; scale = 0x1p-27; } /* Algorithm 312, CACM vol 10, Oct 1967. */ if (a >= 0) { t = sqrt((a + hypot(a, b)) * 0.5); rx = scale * t; ry = scale * b / (2 * t); } else { t = sqrt((-a + hypot(a, b)) * 0.5); rx = scale * fabs(b) / (2 * t); ry = copysign(scale * t, b); } return (CMPLX(rx, ry)); } #if LDBL_MANT_DIG == 53 __weak_reference(csqrt, csqrtl); #endif diff --git a/lib/msun/src/s_csqrtf.c b/lib/msun/src/s_csqrtf.c index ece9f6c13657..b57245166078 100644 --- a/lib/msun/src/s_csqrtf.c +++ b/lib/msun/src/s_csqrtf.c @@ -1,82 +1,81 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "math_private.h" float complex csqrtf(float complex z) { double t; float a, b; a = creal(z); b = cimag(z); /* Handle special cases. */ if (z == 0) return (CMPLXF(0, b)); if (isinf(b)) return (CMPLXF(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ return (CMPLXF(a + 0.0L + t, a + 0.0L + t)); /* NaN + NaN i */ } if (isinf(a)) { /* * csqrtf(inf + NaN i) = inf + NaN i * csqrtf(inf + y i) = inf + 0 i * csqrtf(-inf + NaN i) = NaN +- inf i * csqrtf(-inf + y i) = 0 + inf i */ if (signbit(a)) return (CMPLXF(fabsf(b - b), copysignf(a, b))); else return (CMPLXF(a, copysignf(b - b, b))); } if (isnan(b)) { t = (a - a) / (a - a); /* raise invalid */ return (CMPLXF(b + 0.0L + t, b + 0.0L + t)); /* NaN + NaN i */ } /* * We compute t in double precision to avoid overflow and to * provide correct rounding in nearly all cases. * This is Algorithm 312, CACM vol 10, Oct 1967. */ if (a >= 0) { t = sqrt((a + hypot(a, b)) * 0.5); return (CMPLXF(t, b / (2 * t))); } else { t = sqrt((-a + hypot(a, b)) * 0.5); return (CMPLXF(fabsf(b) / (2 * t), copysignf(t, b))); } } diff --git a/lib/msun/src/s_csqrtl.c b/lib/msun/src/s_csqrtl.c index b0fc37c902f1..0f375f3c2349 100644 --- a/lib/msun/src/s_csqrtl.c +++ b/lib/msun/src/s_csqrtl.c @@ -1,124 +1,123 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "math_private.h" /* * Several thresholds require a 15-bit exponent and also the usual bias. * s_logl.c and e_hypotl have less hard-coding but end up requiring the * same for the exponent and more for the mantissa. */ #if LDBL_MAX_EXP != 0x4000 #error "Unsupported long double format" #endif /* * Overflow must be avoided for components >= LDBL_MAX / (1 + sqrt(2)). * The precise threshold is nontrivial to determine and spell, so use a * lower threshold of approximaely LDBL_MAX / 4, and don't use LDBL_MAX * to spell this since LDBL_MAX is broken on i386 (it overflows in 53-bit * precision). */ #define THRESH 0x1p16382L long double complex csqrtl(long double complex z) { long double complex result; long double a, b, rx, ry, scale, t; a = creall(z); b = cimagl(z); /* Handle special cases. */ if (z == 0) return (CMPLXL(0, b)); if (isinf(b)) return (CMPLXL(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ return (CMPLXL(a + 0.0L + t, a + 0.0L + t)); /* NaN + NaN i */ } if (isinf(a)) { /* * csqrt(inf + NaN i) = inf + NaN i * csqrt(inf + y i) = inf + 0 i * csqrt(-inf + NaN i) = NaN +- inf i * csqrt(-inf + y i) = 0 + inf i */ if (signbit(a)) return (CMPLXL(fabsl(b - b), copysignl(a, b))); else return (CMPLXL(a, copysignl(b - b, b))); } if (isnan(b)) { t = (a - a) / (a - a); /* raise invalid */ return (CMPLXL(b + 0.0L + t, b + 0.0L + t)); /* NaN + NaN i */ } /* Scale to avoid overflow. */ if (fabsl(a) >= THRESH || fabsl(b) >= THRESH) { /* * Don't scale a or b if this might give (spurious) * underflow. Then the unscaled value is an equivalent * infinitesmal (or 0). */ if (fabsl(a) >= 0x1p-16380L) a *= 0.25; if (fabsl(b) >= 0x1p-16380L) b *= 0.25; scale = 2; } else { scale = 1; } /* Scale to reduce inaccuracies when both components are denormal. */ if (fabsl(a) < 0x1p-16382L && fabsl(b) < 0x1p-16382L) { a *= 0x1p64; b *= 0x1p64; scale = 0x1p-32; } /* Algorithm 312, CACM vol 10, Oct 1967. */ if (a >= 0) { t = sqrtl((a + hypotl(a, b)) * 0.5); rx = scale * t; ry = scale * b / (2 * t); } else { t = sqrtl((-a + hypotl(a, b)) * 0.5); rx = scale * fabsl(b) / (2 * t); ry = copysignl(scale * t, b); } return (CMPLXL(rx, ry)); } diff --git a/lib/msun/src/s_ctanh.c b/lib/msun/src/s_ctanh.c index 33186510a8a3..690436343437 100644 --- a/lib/msun/src/s_ctanh.c +++ b/lib/msun/src/s_ctanh.c @@ -1,147 +1,146 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Hyperbolic tangent of a complex argument z = x + I y. * * The algorithm is from: * * W. Kahan. Branch Cuts for Complex Elementary Functions or Much * Ado About Nothing's Sign Bit. In The State of the Art in * Numerical Analysis, pp. 165 ff. Iserles and Powell, eds., 1987. * * Method: * * Let t = tan(x) * beta = 1/cos^2(y) * s = sinh(x) * rho = cosh(x) * * We have: * * tanh(z) = sinh(z) / cosh(z) * * sinh(x) cos(y) + I cosh(x) sin(y) * = --------------------------------- * cosh(x) cos(y) + I sinh(x) sin(y) * * cosh(x) sinh(x) / cos^2(y) + I tan(y) * = ------------------------------------- * 1 + sinh^2(x) / cos^2(y) * * beta rho s + I t * = ---------------- * 1 + beta s^2 * * Modifications: * * I omitted the original algorithm's handling of overflow in tan(x) after * verifying with nearpi.c that this can't happen in IEEE single or double * precision. I also handle large x differently. */ -#include #include #include #include "math_private.h" double complex ctanh(double complex z) { double x, y; double t, beta, s, rho, denom; uint32_t hx, ix, lx; x = creal(z); y = cimag(z); EXTRACT_WORDS(hx, lx, x); ix = hx & 0x7fffffff; /* * ctanh(NaN +- I 0) = d(NaN) +- I 0 * * ctanh(NaN + I y) = d(NaN,y) + I d(NaN,y) for y != 0 * * The imaginary part has the sign of x*sin(2*y), but there's no * special effort to get this right. * * ctanh(+-Inf +- I Inf) = +-1 +- I 0 * * ctanh(+-Inf + I y) = +-1 + I 0 sin(2y) for y finite * * The imaginary part of the sign is unspecified. This special * case is only needed to avoid a spurious invalid exception when * y is infinite. */ if (ix >= 0x7ff00000) { if ((ix & 0xfffff) | lx) /* x is NaN */ return (CMPLX(nan_mix(x, y), y == 0 ? y : nan_mix(x, y))); SET_HIGH_WORD(x, hx - 0x40000000); /* x = copysign(1, x) */ return (CMPLX(x, copysign(0, isinf(y) ? y : sin(y) * cos(y)))); } /* * ctanh(+-0 + i NAN) = +-0 + i NaN * ctanh(+-0 +- i Inf) = +-0 + i NaN * ctanh(x + i NAN) = NaN + i NaN * ctanh(x +- i Inf) = NaN + i NaN */ if (!isfinite(y)) return (CMPLX(x ? y - y : x, y - y)); /* * ctanh(+-huge +- I y) ~= +-1 +- I 2sin(2y)/exp(2x), using the * approximation sinh^2(huge) ~= exp(2*huge) / 4. * We use a modified formula to avoid spurious overflow. */ if (ix >= 0x40360000) { /* |x| >= 22 */ double exp_mx = exp(-fabs(x)); return (CMPLX(copysign(1, x), 4 * sin(y) * cos(y) * exp_mx * exp_mx)); } /* Kahan's algorithm */ t = tan(y); beta = 1.0 + t * t; /* = 1 / cos^2(y) */ s = sinh(x); rho = sqrt(1 + s * s); /* = cosh(x) */ denom = 1 + beta * s * s; return (CMPLX((beta * rho * s) / denom, t / denom)); } double complex ctan(double complex z) { /* ctan(z) = -I * ctanh(I * z) = I * conj(ctanh(I * conj(z))) */ z = ctanh(CMPLX(cimag(z), creal(z))); return (CMPLX(cimag(z), creal(z))); } diff --git a/lib/msun/src/s_ctanhf.c b/lib/msun/src/s_ctanhf.c index c2fb2f8618f6..551e143a3d27 100644 --- a/lib/msun/src/s_ctanhf.c +++ b/lib/msun/src/s_ctanhf.c @@ -1,85 +1,84 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Hyperbolic tangent of a complex argument z. See s_ctanh.c for details. */ -#include #include #include #include "math_private.h" float complex ctanhf(float complex z) { float x, y; float t, beta, s, rho, denom; uint32_t hx, ix; x = crealf(z); y = cimagf(z); GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x7f800000) { if (ix & 0x7fffff) return (CMPLXF(nan_mix(x, y), y == 0 ? y : nan_mix(x, y))); SET_FLOAT_WORD(x, hx - 0x40000000); return (CMPLXF(x, copysignf(0, isinf(y) ? y : sinf(y) * cosf(y)))); } if (!isfinite(y)) return (CMPLXF(ix ? y - y : x, y - y)); if (ix >= 0x41300000) { /* |x| >= 11 */ float exp_mx = expf(-fabsf(x)); return (CMPLXF(copysignf(1, x), 4 * sinf(y) * cosf(y) * exp_mx * exp_mx)); } t = tanf(y); beta = 1.0 + t * t; s = sinhf(x); rho = sqrtf(1 + s * s); denom = 1 + beta * s * s; return (CMPLXF((beta * rho * s) / denom, t / denom)); } float complex ctanf(float complex z) { z = ctanhf(CMPLXF(cimagf(z), crealf(z))); return (CMPLXF(cimagf(z), crealf(z))); } diff --git a/lib/msun/src/s_erf.c b/lib/msun/src/s_erf.c index 6fc9e56d11af..51f4d58a6730 100644 --- a/lib/msun/src/s_erf.c +++ b/lib/msun/src/s_erf.c @@ -1,307 +1,306 @@ /* @(#)s_erf.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* double erf(double x) * double erfc(double x) * x * 2 |\ * erf(x) = --------- | exp(-t*t)dt * sqrt(pi) \| * 0 * * erfc(x) = 1-erf(x) * Note that * erf(-x) = -erf(x) * erfc(-x) = 2 - erfc(x) * * Method: * 1. For |x| in [0, 0.84375] * erf(x) = x + x*R(x^2) * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] * where R = P/Q where P is an odd poly of degree 8 and * Q is an odd poly of degree 10. * -57.90 * | R - (erf(x)-x)/x | <= 2 * * * Remark. The formula is derived by noting * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) * and that * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 * is close to one. The interval is chosen because the fix * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is * near 0.6174), and by some experiment, 0.84375 is chosen to * guarantee the error is less than one ulp for erf. * * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and * c = 0.84506291151 rounded to single (24 bits) * erf(x) = sign(x) * (c + P1(s)/Q1(s)) * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 * 1+(c+P1(s)/Q1(s)) if x < 0 * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 * Remark: here we use the taylor series expansion at x=1. * erf(1+s) = erf(1) + s*Poly(s) * = 0.845.. + P1(s)/Q1(s) * That is, we use rational approximation to approximate * erf(1+s) - (c = (single)0.84506291151) * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] * where * P1(s) = degree 6 poly in s * Q1(s) = degree 6 poly in s * * 3. For x in [1.25,1/0.35(~2.857143)], * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) * erf(x) = 1 - erfc(x) * where * R1(z) = degree 7 poly in z, (z=1/x^2) * S1(z) = degree 8 poly in z * * 4. For x in [1/0.35,28] * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 * erf(x) = sign(x) *(1 - tiny) (raise inexact) * erfc(x) = tiny*tiny (raise underflow) if x > 0 * = 2 - tiny if x<0 * * 7. Special case: * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, * erfc/erf(NaN) is NaN */ #include #include "math.h" #include "math_private.h" /* XXX Prevent compilers from erroneously constant folding: */ static const volatile double tiny= 1e-300; static const double half= 0.5, one = 1, two = 2, /* c = (float)0.84506291151 */ erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ /* * In the domain [0, 2**-28], only the first term in the power series * expansion of erf(x) is used. The magnitude of the first neglected * terms is less than 2**-84. */ efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ /* * Coefficients for approximation to erf on [0,0.84375] */ pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ /* * Coefficients for approximation to erf in [0.84375,1.25] */ pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ /* * Coefficients for approximation to erfc in [1.25,1/0.35] */ ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ /* * Coefficients for approximation to erfc in [1/.35,28] */ rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ double erf(double x) { int32_t hx,ix,i; double R,S,P,Q,s,y,z,r; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) { /* erf(nan)=nan */ i = ((u_int32_t)hx>>31)<<1; return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ } if(ix < 0x3feb0000) { /* |x|<0.84375 */ if(ix < 0x3e300000) { /* |x|<2**-28 */ if (ix < 0x00800000) return (8*x+efx8*x)/8; /* avoid spurious underflow */ return x + efx*x; } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; return x + x*y; } if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ s = fabs(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) return erx + P/Q; else return -erx - P/Q; } if (ix >= 0x40180000) { /* inf>|x|>=6 */ if(hx>=0) return one-tiny; else return tiny-one; } x = fabs(x); s = one/(x*x); if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*sa8))))))); } else { /* |x| >= 1/0.35 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))); } z = x; SET_LOW_WORD(z,0); r = exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S); if(hx>=0) return one-r/x; else return r/x-one; } #if (LDBL_MANT_DIG == 53) __weak_reference(erf, erfl); #endif double erfc(double x) { int32_t hx,ix; double R,S,P,Q,s,y,z,r; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) { /* erfc(nan)=nan */ /* erfc(+-inf)=0,2 */ return (double)(((u_int32_t)hx>>31)<<1)+one/x; } if(ix < 0x3feb0000) { /* |x|<0.84375 */ if(ix < 0x3c700000) /* |x|<2**-56 */ return one-x; z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; if(hx < 0x3fd00000) { /* x<1/4 */ return one-(x+x*y); } else { r = x*y; r += (x-half); return half - r ; } } if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ s = fabs(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) { z = one-erx; return z - P/Q; } else { z = erx+P/Q; return one+z; } } if (ix < 0x403c0000) { /* |x|<28 */ x = fabs(x); s = one/(x*x); if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+ s*sa8))))))); } else { /* |x| >= 1/.35 ~ 2.857143 */ if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))); } z = x; SET_LOW_WORD(z,0); r = exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S); if(hx>0) return r/x; else return two-r/x; } else { if(hx>0) return tiny*tiny; else return two-tiny; } } #if (LDBL_MANT_DIG == 53) __weak_reference(erfc, erfcl); #endif diff --git a/lib/msun/src/s_erff.c b/lib/msun/src/s_erff.c index bf011b312bfb..6c8f4060c802 100644 --- a/lib/msun/src/s_erff.c +++ b/lib/msun/src/s_erff.c @@ -1,179 +1,178 @@ /* s_erff.c -- float version of s_erf.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" /* XXX Prevent compilers from erroneously constant folding: */ static const volatile float tiny = 1e-30; static const float half= 0.5, one = 1, two = 2, erx = 8.42697144e-01, /* 0x3f57bb00 */ /* * In the domain [0, 2**-14], only the first term in the power series * expansion of erf(x) is used. The magnitude of the first neglected * terms is less than 2**-42. */ efx = 1.28379166e-01, /* 0x3e0375d4 */ efx8= 1.02703333e+00, /* 0x3f8375d4 */ /* * Domain [0, 0.84375], range ~[-5.4419e-10, 5.5179e-10]: * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-31 */ pp0 = 1.28379166e-01, /* 0x3e0375d4 */ pp1 = -3.36030394e-01, /* 0xbeac0c2d */ pp2 = -1.86261395e-03, /* 0xbaf422f4 */ qq1 = 3.12324315e-01, /* 0x3e9fe8f9 */ qq2 = 2.16070414e-02, /* 0x3cb10140 */ qq3 = -1.98859372e-03, /* 0xbb025311 */ /* * Domain [0.84375, 1.25], range ~[-1.023e-9, 1.023e-9]: * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-31 */ pa0 = 3.65041046e-06, /* 0x3674f993 */ pa1 = 4.15109307e-01, /* 0x3ed48935 */ pa2 = -2.09395722e-01, /* 0xbe566bd5 */ pa3 = 8.67677554e-02, /* 0x3db1b34b */ qa1 = 4.95560974e-01, /* 0x3efdba2b */ qa2 = 3.71248513e-01, /* 0x3ebe1449 */ qa3 = 3.92478965e-02, /* 0x3d20c267 */ /* * Domain [1.25,1/0.35], range ~[-4.821e-9, 4.927e-9]: * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-28 */ ra0 = -9.88156721e-03, /* 0xbc21e64c */ ra1 = -5.43658376e-01, /* 0xbf0b2d32 */ ra2 = -1.66828310e+00, /* 0xbfd58a4d */ ra3 = -6.91554189e-01, /* 0xbf3109b2 */ sa1 = 4.48581553e+00, /* 0x408f8bcd */ sa2 = 4.10799170e+00, /* 0x408374ab */ sa3 = 5.53855181e-01, /* 0x3f0dc974 */ /* * Domain [2.85715, 11], range ~[-1.484e-9, 1.505e-9]: * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-30 */ rb0 = -9.86496918e-03, /* 0xbc21a0ae */ rb1 = -5.48049808e-01, /* 0xbf0c4cfe */ rb2 = -1.84115684e+00, /* 0xbfebab07 */ sb1 = 4.87132740e+00, /* 0x409be1ea */ sb2 = 3.04982710e+00, /* 0x4043305e */ sb3 = -7.61900663e-01; /* 0xbf430bec */ float erff(float x) { int32_t hx,ix,i; float R,S,P,Q,s,y,z,r; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) { /* erff(nan)=nan */ i = ((u_int32_t)hx>>31)<<1; return (float)(1-i)+one/x; /* erff(+-inf)=+-1 */ } if(ix < 0x3f580000) { /* |x|<0.84375 */ if(ix < 0x38800000) { /* |x|<2**-14 */ if (ix < 0x04000000) /* |x|<0x1p-119 */ return (8*x+efx8*x)/8; /* avoid spurious underflow */ return x + efx*x; } z = x*x; r = pp0+z*(pp1+z*pp2); s = one+z*(qq1+z*(qq2+z*qq3)); y = r/s; return x + x*y; } if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ s = fabsf(x)-one; P = pa0+s*(pa1+s*(pa2+s*pa3)); Q = one+s*(qa1+s*(qa2+s*qa3)); if(hx>=0) return erx + P/Q; else return -erx - P/Q; } if (ix >= 0x40800000) { /* inf>|x|>=4 */ if(hx>=0) return one-tiny; else return tiny-one; } x = fabsf(x); s = one/(x*x); if(ix< 0x4036db8c) { /* |x| < 2.85715 ~ 1/0.35 */ R=ra0+s*(ra1+s*(ra2+s*ra3)); S=one+s*(sa1+s*(sa2+s*sa3)); } else { /* |x| >= 2.85715 ~ 1/0.35 */ R=rb0+s*(rb1+s*rb2); S=one+s*(sb1+s*(sb2+s*sb3)); } SET_FLOAT_WORD(z,hx&0xffffe000); r = expf(-z*z-0.5625F)*expf((z-x)*(z+x)+R/S); if(hx>=0) return one-r/x; else return r/x-one; } float erfcf(float x) { int32_t hx,ix; float R,S,P,Q,s,y,z,r; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) { /* erfcf(nan)=nan */ /* erfcf(+-inf)=0,2 */ return (float)(((u_int32_t)hx>>31)<<1)+one/x; } if(ix < 0x3f580000) { /* |x|<0.84375 */ if(ix < 0x33800000) /* |x|<2**-24 */ return one-x; z = x*x; r = pp0+z*(pp1+z*pp2); s = one+z*(qq1+z*(qq2+z*qq3)); y = r/s; if(hx < 0x3e800000) { /* x<1/4 */ return one-(x+x*y); } else { r = x*y; r += (x-half); return half - r ; } } if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ s = fabsf(x)-one; P = pa0+s*(pa1+s*(pa2+s*pa3)); Q = one+s*(qa1+s*(qa2+s*qa3)); if(hx>=0) { z = one-erx; return z - P/Q; } else { z = erx+P/Q; return one+z; } } if (ix < 0x41300000) { /* |x|<11 */ x = fabsf(x); s = one/(x*x); if(ix< 0x4036db8c) { /* |x| < 2.85715 ~ 1/.35 */ R=ra0+s*(ra1+s*(ra2+s*ra3)); S=one+s*(sa1+s*(sa2+s*sa3)); } else { /* |x| >= 2.85715 ~ 1/.35 */ if(hx<0&&ix>=0x40a00000) return two-tiny;/* x < -5 */ R=rb0+s*(rb1+s*rb2); S=one+s*(sb1+s*(sb2+s*sb3)); } SET_FLOAT_WORD(z,hx&0xffffe000); r = expf(-z*z-0.5625F)*expf((z-x)*(z+x)+R/S); if(hx>0) return r/x; else return two-r/x; } else { if(hx>0) return tiny*tiny; else return two-tiny; } } diff --git a/lib/msun/src/s_exp2.c b/lib/msun/src/s_exp2.c index 5bf9d65975e0..338312f0de97 100644 --- a/lib/msun/src/s_exp2.c +++ b/lib/msun/src/s_exp2.c @@ -1,397 +1,396 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" #define TBLBITS 8 #define TBLSIZE (1 << TBLBITS) static const double redux = 0x1.8p52 / TBLSIZE, P1 = 0x1.62e42fefa39efp-1, P2 = 0x1.ebfbdff82c575p-3, P3 = 0x1.c6b08d704a0a6p-5, P4 = 0x1.3b2ab88f70400p-7, P5 = 0x1.5d88003875c74p-10; static volatile double huge = 0x1p1000, twom1000 = 0x1p-1000; static const double tbl[TBLSIZE * 2] = { /* exp2(z + eps) eps */ 0x1.6a09e667f3d5dp-1, 0x1.9880p-44, 0x1.6b052fa751744p-1, 0x1.8000p-50, 0x1.6c012750bd9fep-1, -0x1.8780p-45, 0x1.6cfdcddd476bfp-1, 0x1.ec00p-46, 0x1.6dfb23c651a29p-1, -0x1.8000p-50, 0x1.6ef9298593ae3p-1, -0x1.c000p-52, 0x1.6ff7df9519386p-1, -0x1.fd80p-45, 0x1.70f7466f42da3p-1, -0x1.c880p-45, 0x1.71f75e8ec5fc3p-1, 0x1.3c00p-46, 0x1.72f8286eacf05p-1, -0x1.8300p-44, 0x1.73f9a48a58152p-1, -0x1.0c00p-47, 0x1.74fbd35d7ccfcp-1, 0x1.f880p-45, 0x1.75feb564267f1p-1, 0x1.3e00p-47, 0x1.77024b1ab6d48p-1, -0x1.7d00p-45, 0x1.780694fde5d38p-1, -0x1.d000p-50, 0x1.790b938ac1d00p-1, 0x1.3000p-49, 0x1.7a11473eb0178p-1, -0x1.d000p-49, 0x1.7b17b0976d060p-1, 0x1.0400p-45, 0x1.7c1ed0130c133p-1, 0x1.0000p-53, 0x1.7d26a62ff8636p-1, -0x1.6900p-45, 0x1.7e2f336cf4e3bp-1, -0x1.2e00p-47, 0x1.7f3878491c3e8p-1, -0x1.4580p-45, 0x1.80427543e1b4ep-1, 0x1.3000p-44, 0x1.814d2add1071ap-1, 0x1.f000p-47, 0x1.82589994ccd7ep-1, -0x1.1c00p-45, 0x1.8364c1eb942d0p-1, 0x1.9d00p-45, 0x1.8471a4623cab5p-1, 0x1.7100p-43, 0x1.857f4179f5bbcp-1, 0x1.2600p-45, 0x1.868d99b4491afp-1, -0x1.2c40p-44, 0x1.879cad931a395p-1, -0x1.3000p-45, 0x1.88ac7d98a65b8p-1, -0x1.a800p-45, 0x1.89bd0a4785800p-1, -0x1.d000p-49, 0x1.8ace5422aa223p-1, 0x1.3280p-44, 0x1.8be05bad619fap-1, 0x1.2b40p-43, 0x1.8cf3216b54383p-1, -0x1.ed00p-45, 0x1.8e06a5e08664cp-1, -0x1.0500p-45, 0x1.8f1ae99157807p-1, 0x1.8280p-45, 0x1.902fed0282c0ep-1, -0x1.cb00p-46, 0x1.9145b0b91ff96p-1, -0x1.5e00p-47, 0x1.925c353aa2ff9p-1, 0x1.5400p-48, 0x1.93737b0cdc64ap-1, 0x1.7200p-46, 0x1.948b82b5f98aep-1, -0x1.9000p-47, 0x1.95a44cbc852cbp-1, 0x1.5680p-45, 0x1.96bdd9a766f21p-1, -0x1.6d00p-44, 0x1.97d829fde4e2ap-1, -0x1.1000p-47, 0x1.98f33e47a23a3p-1, 0x1.d000p-45, 0x1.9a0f170ca0604p-1, -0x1.8a40p-44, 0x1.9b2bb4d53ff89p-1, 0x1.55c0p-44, 0x1.9c49182a3f15bp-1, 0x1.6b80p-45, 0x1.9d674194bb8c5p-1, -0x1.c000p-49, 0x1.9e86319e3238ep-1, 0x1.7d00p-46, 0x1.9fa5e8d07f302p-1, 0x1.6400p-46, 0x1.a0c667b5de54dp-1, -0x1.5000p-48, 0x1.a1e7aed8eb8f6p-1, 0x1.9e00p-47, 0x1.a309bec4a2e27p-1, 0x1.ad80p-45, 0x1.a42c980460a5dp-1, -0x1.af00p-46, 0x1.a5503b23e259bp-1, 0x1.b600p-47, 0x1.a674a8af46213p-1, 0x1.8880p-44, 0x1.a799e1330b3a7p-1, 0x1.1200p-46, 0x1.a8bfe53c12e8dp-1, 0x1.6c00p-47, 0x1.a9e6b5579fcd2p-1, -0x1.9b80p-45, 0x1.ab0e521356fb8p-1, 0x1.b700p-45, 0x1.ac36bbfd3f381p-1, 0x1.9000p-50, 0x1.ad5ff3a3c2780p-1, 0x1.4000p-49, 0x1.ae89f995ad2a3p-1, -0x1.c900p-45, 0x1.afb4ce622f367p-1, 0x1.6500p-46, 0x1.b0e07298db790p-1, 0x1.fd40p-45, 0x1.b20ce6c9a89a9p-1, 0x1.2700p-46, 0x1.b33a2b84f1a4bp-1, 0x1.d470p-43, 0x1.b468415b747e7p-1, -0x1.8380p-44, 0x1.b59728de5593ap-1, 0x1.8000p-54, 0x1.b6c6e29f1c56ap-1, 0x1.ad00p-47, 0x1.b7f76f2fb5e50p-1, 0x1.e800p-50, 0x1.b928cf22749b2p-1, -0x1.4c00p-47, 0x1.ba5b030a10603p-1, -0x1.d700p-47, 0x1.bb8e0b79a6f66p-1, 0x1.d900p-47, 0x1.bcc1e904bc1ffp-1, 0x1.2a00p-47, 0x1.bdf69c3f3a16fp-1, -0x1.f780p-46, 0x1.bf2c25bd71db8p-1, -0x1.0a00p-46, 0x1.c06286141b2e9p-1, -0x1.1400p-46, 0x1.c199bdd8552e0p-1, 0x1.be00p-47, 0x1.c2d1cd9fa64eep-1, -0x1.9400p-47, 0x1.c40ab5fffd02fp-1, -0x1.ed00p-47, 0x1.c544778fafd15p-1, 0x1.9660p-44, 0x1.c67f12e57d0cbp-1, -0x1.a100p-46, 0x1.c7ba88988c1b6p-1, -0x1.8458p-42, 0x1.c8f6d9406e733p-1, -0x1.a480p-46, 0x1.ca3405751c4dfp-1, 0x1.b000p-51, 0x1.cb720dcef9094p-1, 0x1.1400p-47, 0x1.ccb0f2e6d1689p-1, 0x1.0200p-48, 0x1.cdf0b555dc412p-1, 0x1.3600p-48, 0x1.cf3155b5bab3bp-1, -0x1.6900p-47, 0x1.d072d4a0789bcp-1, 0x1.9a00p-47, 0x1.d1b532b08c8fap-1, -0x1.5e00p-46, 0x1.d2f87080d8a85p-1, 0x1.d280p-46, 0x1.d43c8eacaa203p-1, 0x1.1a00p-47, 0x1.d5818dcfba491p-1, 0x1.f000p-50, 0x1.d6c76e862e6a1p-1, -0x1.3a00p-47, 0x1.d80e316c9834ep-1, -0x1.cd80p-47, 0x1.d955d71ff6090p-1, 0x1.4c00p-48, 0x1.da9e603db32aep-1, 0x1.f900p-48, 0x1.dbe7cd63a8325p-1, 0x1.9800p-49, 0x1.dd321f301b445p-1, -0x1.5200p-48, 0x1.de7d5641c05bfp-1, -0x1.d700p-46, 0x1.dfc97337b9aecp-1, -0x1.6140p-46, 0x1.e11676b197d5ep-1, 0x1.b480p-47, 0x1.e264614f5a3e7p-1, 0x1.0ce0p-43, 0x1.e3b333b16ee5cp-1, 0x1.c680p-47, 0x1.e502ee78b3fb4p-1, -0x1.9300p-47, 0x1.e653924676d68p-1, -0x1.5000p-49, 0x1.e7a51fbc74c44p-1, -0x1.7f80p-47, 0x1.e8f7977cdb726p-1, -0x1.3700p-48, 0x1.ea4afa2a490e8p-1, 0x1.5d00p-49, 0x1.eb9f4867ccae4p-1, 0x1.61a0p-46, 0x1.ecf482d8e680dp-1, 0x1.5500p-48, 0x1.ee4aaa2188514p-1, 0x1.6400p-51, 0x1.efa1bee615a13p-1, -0x1.e800p-49, 0x1.f0f9c1cb64106p-1, -0x1.a880p-48, 0x1.f252b376bb963p-1, -0x1.c900p-45, 0x1.f3ac948dd7275p-1, 0x1.a000p-53, 0x1.f50765b6e4524p-1, -0x1.4f00p-48, 0x1.f6632798844fdp-1, 0x1.a800p-51, 0x1.f7bfdad9cbe38p-1, 0x1.abc0p-48, 0x1.f91d802243c82p-1, -0x1.4600p-50, 0x1.fa7c1819e908ep-1, -0x1.b0c0p-47, 0x1.fbdba3692d511p-1, -0x1.0e00p-51, 0x1.fd3c22b8f7194p-1, -0x1.0de8p-46, 0x1.fe9d96b2a23eep-1, 0x1.e430p-49, 0x1.0000000000000p+0, 0x0.0000p+0, 0x1.00b1afa5abcbep+0, -0x1.3400p-52, 0x1.0163da9fb3303p+0, -0x1.2170p-46, 0x1.02168143b0282p+0, 0x1.a400p-52, 0x1.02c9a3e77806cp+0, 0x1.f980p-49, 0x1.037d42e11bbcap+0, -0x1.7400p-51, 0x1.04315e86e7f89p+0, 0x1.8300p-50, 0x1.04e5f72f65467p+0, -0x1.a3f0p-46, 0x1.059b0d315855ap+0, -0x1.2840p-47, 0x1.0650a0e3c1f95p+0, 0x1.1600p-48, 0x1.0706b29ddf71ap+0, 0x1.5240p-46, 0x1.07bd42b72a82dp+0, -0x1.9a00p-49, 0x1.0874518759bd0p+0, 0x1.6400p-49, 0x1.092bdf66607c8p+0, -0x1.0780p-47, 0x1.09e3ecac6f383p+0, -0x1.8000p-54, 0x1.0a9c79b1f3930p+0, 0x1.fa00p-48, 0x1.0b5586cf988fcp+0, -0x1.ac80p-48, 0x1.0c0f145e46c8ap+0, 0x1.9c00p-50, 0x1.0cc922b724816p+0, 0x1.5200p-47, 0x1.0d83b23395dd8p+0, -0x1.ad00p-48, 0x1.0e3ec32d3d1f3p+0, 0x1.bac0p-46, 0x1.0efa55fdfa9a6p+0, -0x1.4e80p-47, 0x1.0fb66affed2f0p+0, -0x1.d300p-47, 0x1.1073028d7234bp+0, 0x1.1500p-48, 0x1.11301d0125b5bp+0, 0x1.c000p-49, 0x1.11edbab5e2af9p+0, 0x1.6bc0p-46, 0x1.12abdc06c31d5p+0, 0x1.8400p-49, 0x1.136a814f2047dp+0, -0x1.ed00p-47, 0x1.1429aaea92de9p+0, 0x1.8e00p-49, 0x1.14e95934f3138p+0, 0x1.b400p-49, 0x1.15a98c8a58e71p+0, 0x1.5300p-47, 0x1.166a45471c3dfp+0, 0x1.3380p-47, 0x1.172b83c7d5211p+0, 0x1.8d40p-45, 0x1.17ed48695bb9fp+0, -0x1.5d00p-47, 0x1.18af9388c8d93p+0, -0x1.c880p-46, 0x1.1972658375d66p+0, 0x1.1f00p-46, 0x1.1a35beb6fcba7p+0, 0x1.0480p-46, 0x1.1af99f81387e3p+0, -0x1.7390p-43, 0x1.1bbe084045d54p+0, 0x1.4e40p-45, 0x1.1c82f95281c43p+0, -0x1.a200p-47, 0x1.1d4873168b9b2p+0, 0x1.3800p-49, 0x1.1e0e75eb44031p+0, 0x1.ac00p-49, 0x1.1ed5022fcd938p+0, 0x1.1900p-47, 0x1.1f9c18438cdf7p+0, -0x1.b780p-46, 0x1.2063b88628d8fp+0, 0x1.d940p-45, 0x1.212be3578a81ep+0, 0x1.8000p-50, 0x1.21f49917ddd41p+0, 0x1.b340p-45, 0x1.22bdda2791323p+0, 0x1.9f80p-46, 0x1.2387a6e7561e7p+0, -0x1.9c80p-46, 0x1.2451ffb821427p+0, 0x1.2300p-47, 0x1.251ce4fb2a602p+0, -0x1.3480p-46, 0x1.25e85711eceb0p+0, 0x1.2700p-46, 0x1.26b4565e27d16p+0, 0x1.1d00p-46, 0x1.2780e341de00fp+0, 0x1.1ee0p-44, 0x1.284dfe1f5633ep+0, -0x1.4c00p-46, 0x1.291ba7591bb30p+0, -0x1.3d80p-46, 0x1.29e9df51fdf09p+0, 0x1.8b00p-47, 0x1.2ab8a66d10e9bp+0, -0x1.27c0p-45, 0x1.2b87fd0dada3ap+0, 0x1.a340p-45, 0x1.2c57e39771af9p+0, -0x1.0800p-46, 0x1.2d285a6e402d9p+0, -0x1.ed00p-47, 0x1.2df961f641579p+0, -0x1.4200p-48, 0x1.2ecafa93e2ecfp+0, -0x1.4980p-45, 0x1.2f9d24abd8822p+0, -0x1.6300p-46, 0x1.306fe0a31b625p+0, -0x1.2360p-44, 0x1.31432edeea50bp+0, -0x1.0df8p-40, 0x1.32170fc4cd7b8p+0, -0x1.2480p-45, 0x1.32eb83ba8e9a2p+0, -0x1.5980p-45, 0x1.33c08b2641766p+0, 0x1.ed00p-46, 0x1.3496266e3fa27p+0, -0x1.c000p-50, 0x1.356c55f929f0fp+0, -0x1.0d80p-44, 0x1.36431a2de88b9p+0, 0x1.2c80p-45, 0x1.371a7373aaa39p+0, 0x1.0600p-45, 0x1.37f26231e74fep+0, -0x1.6600p-46, 0x1.38cae6d05d838p+0, -0x1.ae00p-47, 0x1.39a401b713ec3p+0, -0x1.4720p-43, 0x1.3a7db34e5a020p+0, 0x1.8200p-47, 0x1.3b57fbfec6e95p+0, 0x1.e800p-44, 0x1.3c32dc313a8f2p+0, 0x1.f800p-49, 0x1.3d0e544ede122p+0, -0x1.7a00p-46, 0x1.3dea64c1234bbp+0, 0x1.6300p-45, 0x1.3ec70df1c4eccp+0, -0x1.8a60p-43, 0x1.3fa4504ac7e8cp+0, -0x1.cdc0p-44, 0x1.40822c367a0bbp+0, 0x1.5b80p-45, 0x1.4160a21f72e95p+0, 0x1.ec00p-46, 0x1.423fb27094646p+0, -0x1.3600p-46, 0x1.431f5d950a920p+0, 0x1.3980p-45, 0x1.43ffa3f84b9ebp+0, 0x1.a000p-48, 0x1.44e0860618919p+0, -0x1.6c00p-48, 0x1.45c2042a7d201p+0, -0x1.bc00p-47, 0x1.46a41ed1d0016p+0, -0x1.2800p-46, 0x1.4786d668b3326p+0, 0x1.0e00p-44, 0x1.486a2b5c13c00p+0, -0x1.d400p-45, 0x1.494e1e192af04p+0, 0x1.c200p-47, 0x1.4a32af0d7d372p+0, -0x1.e500p-46, 0x1.4b17dea6db801p+0, 0x1.7800p-47, 0x1.4bfdad53629e1p+0, -0x1.3800p-46, 0x1.4ce41b817c132p+0, 0x1.0800p-47, 0x1.4dcb299fddddbp+0, 0x1.c700p-45, 0x1.4eb2d81d8ab96p+0, -0x1.ce00p-46, 0x1.4f9b2769d2d02p+0, 0x1.9200p-46, 0x1.508417f4531c1p+0, -0x1.8c00p-47, 0x1.516daa2cf662ap+0, -0x1.a000p-48, 0x1.5257de83f51eap+0, 0x1.a080p-43, 0x1.5342b569d4edap+0, -0x1.6d80p-45, 0x1.542e2f4f6ac1ap+0, -0x1.2440p-44, 0x1.551a4ca5d94dbp+0, 0x1.83c0p-43, 0x1.56070dde9116bp+0, 0x1.4b00p-45, 0x1.56f4736b529dep+0, 0x1.15a0p-43, 0x1.57e27dbe2c40ep+0, -0x1.9e00p-45, 0x1.58d12d497c76fp+0, -0x1.3080p-45, 0x1.59c0827ff0b4cp+0, 0x1.dec0p-43, 0x1.5ab07dd485427p+0, -0x1.4000p-51, 0x1.5ba11fba87af4p+0, 0x1.0080p-44, 0x1.5c9268a59460bp+0, -0x1.6c80p-45, 0x1.5d84590998e3fp+0, 0x1.69a0p-43, 0x1.5e76f15ad20e1p+0, -0x1.b400p-46, 0x1.5f6a320dcebcap+0, 0x1.7700p-46, 0x1.605e1b976dcb8p+0, 0x1.6f80p-45, 0x1.6152ae6cdf715p+0, 0x1.1000p-47, 0x1.6247eb03a5531p+0, -0x1.5d00p-46, 0x1.633dd1d1929b5p+0, -0x1.2d00p-46, 0x1.6434634ccc313p+0, -0x1.a800p-49, 0x1.652b9febc8efap+0, -0x1.8600p-45, 0x1.6623882553397p+0, 0x1.1fe0p-40, 0x1.671c1c708328ep+0, -0x1.7200p-44, 0x1.68155d44ca97ep+0, 0x1.6800p-49, 0x1.690f4b19e9471p+0, -0x1.9780p-45, }; /* * exp2(x): compute the base 2 exponential of x * * Accuracy: Peak error < 0.503 ulp for normalized results. * * Method: (accurate tables) * * Reduce x: * x = 2**k + y, for integer k and |y| <= 1/2. * Thus we have exp2(x) = 2**k * exp2(y). * * Reduce y: * y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE. * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]), * with |z - eps[i]| <= 2**-9 + 2**-39 for the table used. * * We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via * a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61. * The values in exp2t[] and eps[] are chosen such that * exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such * that exp2t[i] is accurate to 2**-64. * * Note that the range of i is +-TBLSIZE/2, so we actually index the tables * by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are * virtual tables, interleaved in the real table tbl[]. * * This method is due to Gal, with many details due to Gal and Bachelis: * * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991). */ double exp2(double x) { double r, t, twopk, twopkp1000, z; uint32_t hx, ix, lx, i0; int k; /* Filter out exceptional cases. */ GET_HIGH_WORD(hx,x); ix = hx & 0x7fffffff; /* high word of |x| */ if(ix >= 0x40900000) { /* |x| >= 1024 */ if(ix >= 0x7ff00000) { GET_LOW_WORD(lx,x); if(((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0) return (x + x); /* x is NaN or +Inf */ else return (0.0); /* x is -Inf */ } if(x >= 0x1.0p10) return (huge * huge); /* overflow */ if(x <= -0x1.0ccp10) return (twom1000 * twom1000); /* underflow */ } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */ return (1.0 + x); } /* Reduce x, computing z, i0, and k. */ STRICT_ASSIGN(double, t, x + redux); GET_LOW_WORD(i0, t); i0 += TBLSIZE / 2; k = (i0 >> TBLBITS) << 20; i0 = (i0 & (TBLSIZE - 1)) << 1; t -= redux; z = x - t; /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ t = tbl[i0]; /* exp2t[i0] */ z -= tbl[i0 + 1]; /* eps[i0] */ if (k >= -(1021 << 20)) INSERT_WORDS(twopk, 0x3ff00000 + k, 0); else INSERT_WORDS(twopkp1000, 0x3ff00000 + k + (1000 << 20), 0); r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))); /* Scale by 2**(k>>20). */ if(k >= -(1021 << 20)) { if (k == 1024 << 20) return (r * 2.0 * 0x1p1023); return (r * twopk); } else { return (r * twopkp1000 * twom1000); } } #if (LDBL_MANT_DIG == 53) __weak_reference(exp2, exp2l); #endif diff --git a/lib/msun/src/s_exp2f.c b/lib/msun/src/s_exp2f.c index f94cfaf9ce96..85edd611944e 100644 --- a/lib/msun/src/s_exp2f.c +++ b/lib/msun/src/s_exp2f.c @@ -1,137 +1,136 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" #define TBLBITS 4 #define TBLSIZE (1 << TBLBITS) static const float redux = 0x1.8p23f / TBLSIZE, P1 = 0x1.62e430p-1f, P2 = 0x1.ebfbe0p-3f, P3 = 0x1.c6b348p-5f, P4 = 0x1.3b2c9cp-7f; static volatile float huge = 0x1p100f, twom100 = 0x1p-100f; static const double exp2ft[TBLSIZE] = { 0x1.6a09e667f3bcdp-1, 0x1.7a11473eb0187p-1, 0x1.8ace5422aa0dbp-1, 0x1.9c49182a3f090p-1, 0x1.ae89f995ad3adp-1, 0x1.c199bdd85529cp-1, 0x1.d5818dcfba487p-1, 0x1.ea4afa2a490dap-1, 0x1.0000000000000p+0, 0x1.0b5586cf9890fp+0, 0x1.172b83c7d517bp+0, 0x1.2387a6e756238p+0, 0x1.306fe0a31b715p+0, 0x1.3dea64c123422p+0, 0x1.4bfdad5362a27p+0, 0x1.5ab07dd485429p+0, }; /* * exp2f(x): compute the base 2 exponential of x * * Accuracy: Peak error < 0.501 ulp; location of peak: -0.030110927. * * Method: (equally-spaced tables) * * Reduce x: * x = 2**k + y, for integer k and |y| <= 1/2. * Thus we have exp2f(x) = 2**k * exp2(y). * * Reduce y: * y = i/TBLSIZE + z for integer i near y * TBLSIZE. * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z), * with |z| <= 2**-(TBLSIZE+1). * * We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a * degree-4 minimax polynomial with maximum error under 1.4 * 2**-33. * Using double precision for everything except the reduction makes * roundoff error insignificant and simplifies the scaling step. * * This method is due to Tang, but I do not use his suggested parameters: * * Tang, P. Table-driven Implementation of the Exponential Function * in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989). */ float exp2f(float x) { double tv, twopk, u, z; float t; uint32_t hx, ix, i0; int32_t k; /* Filter out exceptional cases. */ GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; /* high word of |x| */ if(ix >= 0x43000000) { /* |x| >= 128 */ if(ix >= 0x7f800000) { if ((ix & 0x7fffff) != 0 || (hx & 0x80000000) == 0) return (x + x); /* x is NaN or +Inf */ else return (0.0); /* x is -Inf */ } if(x >= 0x1.0p7f) return (huge * huge); /* overflow */ if(x <= -0x1.2cp7f) return (twom100 * twom100); /* underflow */ } else if (ix <= 0x33000000) { /* |x| <= 0x1p-25 */ return (1.0f + x); } /* Reduce x, computing z, i0, and k. */ STRICT_ASSIGN(float, t, x + redux); GET_FLOAT_WORD(i0, t); i0 += TBLSIZE / 2; k = (i0 >> TBLBITS) << 20; i0 &= TBLSIZE - 1; t -= redux; z = x - t; INSERT_WORDS(twopk, 0x3ff00000 + k, 0); /* Compute r = exp2(y) = exp2ft[i0] * p(z). */ tv = exp2ft[i0]; u = tv * z; tv = tv + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4); /* Scale by 2**(k>>20). */ return (tv * twopk); } diff --git a/lib/msun/src/s_expm1.c b/lib/msun/src/s_expm1.c index 154a5d8148a5..924b7fbb3d19 100644 --- a/lib/msun/src/s_expm1.c +++ b/lib/msun/src/s_expm1.c @@ -1,220 +1,219 @@ /* @(#)s_expm1.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* expm1(x) * Returns exp(x)-1, the exponential of x minus 1. * * Method * 1. Argument reduction: * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 * * Here a correction term c will be computed to compensate * the error in r when rounded to a floating-point number. * * 2. Approximating expm1(r) by a special rational function on * the interval [0,0.34658]: * Since * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... * we define R1(r*r) by * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) * That is, * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... * We use a special Reme algorithm on [0,0.347] to generate * a polynomial of degree 5 in r*r to approximate R1. The * maximum error of this polynomial approximation is bounded * by 2**-61. In other words, * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 * where Q1 = -1.6666666666666567384E-2, * Q2 = 3.9682539681370365873E-4, * Q3 = -9.9206344733435987357E-6, * Q4 = 2.5051361420808517002E-7, * Q5 = -6.2843505682382617102E-9; * z = r*r, * with error bounded by * | 5 | -61 * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 * | | * * expm1(r) = exp(r)-1 is then computed by the following * specific way which minimize the accumulation rounding error: * 2 3 * r r [ 3 - (R1 + R1*r/2) ] * expm1(r) = r + --- + --- * [--------------------] * 2 2 [ 6 - r*(3 - R1*r/2) ] * * To compensate the error in the argument reduction, we use * expm1(r+c) = expm1(r) + c + expm1(r)*c * ~ expm1(r) + c + r*c * Thus c+r*c will be added in as the correction terms for * expm1(r+c). Now rearrange the term to avoid optimization * screw up: * ( 2 2 ) * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) * ( ) * * = r - E * 3. Scale back to obtain expm1(x): * From step 1, we have * expm1(x) = either 2^k*[expm1(r)+1] - 1 * = or 2^k*[expm1(r) + (1-2^-k)] * 4. Implementation notes: * (A). To save one multiplication, we scale the coefficient Qi * to Qi*2^i, and replace z by (x^2)/2. * (B). To achieve maximum accuracy, we compute expm1(x) by * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) * (ii) if k=0, return r-E * (iii) if k=-1, return 0.5*(r-E)-0.5 * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) * else return 1.0+2.0*(r-E); * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else * (vii) return 2^k(1-((E+2^-k)-r)) * * Special cases: * expm1(INF) is INF, expm1(NaN) is NaN; * expm1(-INF) is -1, and * for finite argument, only expm1(0)=0 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 7.09782712893383973096e+02 then expm1(x) overflow * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include "math.h" #include "math_private.h" static const double one = 1.0, tiny = 1.0e-300, o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ /* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */ Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ static volatile double huge = 1.0e+300; double expm1(double x) { double y,hi,lo,c,t,e,hxs,hfx,r1,twopk; int32_t k,xsb; u_int32_t hx; GET_HIGH_WORD(hx,x); xsb = hx&0x80000000; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out huge and non-finite argument */ if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { u_int32_t low; GET_LOW_WORD(low,x); if(((hx&0xfffff)|low)!=0) return x+x; /* NaN */ else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ } if(x > o_threshold) return huge*huge; /* overflow */ } if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ if(x+tiny<0.0) /* raise inexact */ return tiny-one; /* return -1 */ } } /* argument reduction */ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ if(xsb==0) {hi = x - ln2_hi; lo = ln2_lo; k = 1;} else {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} } else { k = invln2*x+((xsb==0)?0.5:-0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } STRICT_ASSIGN(double, x, hi - lo); c = (hi-x)-lo; } else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ t = huge+x; /* return x with inexact flags when x!=0 */ return x - (t-(huge+x)); } else k = 0; /* x is now in primary range */ hfx = 0.5*x; hxs = x*hfx; r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); t = 3.0-r1*hfx; e = hxs*((r1-t)/(6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { INSERT_WORDS(twopk,((u_int32_t)(0x3ff+k))<<20,0); /* 2^k */ e = (x*(e-c)-c); e -= hxs; if(k== -1) return 0.5*(x-e)-0.5; if(k==1) { if(x < -0.25) return -2.0*(e-(x+0.5)); else return one+2.0*(x-e); } if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ y = one-(e-x); if (k == 1024) y = y*2.0*0x1p1023; else y = y*twopk; return y-one; } t = one; if(k<20) { SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */ y = t-(e-x); y = y*twopk; } else { SET_HIGH_WORD(t,((0x3ff-k)<<20)); /* 2^-k */ y = x-(e+t); y += one; y = y*twopk; } } return y; } #if (LDBL_MANT_DIG == 53) __weak_reference(expm1, expm1l); #endif diff --git a/lib/msun/src/s_expm1f.c b/lib/msun/src/s_expm1f.c index 831c0caa6db8..6887bf265272 100644 --- a/lib/msun/src/s_expm1f.c +++ b/lib/msun/src/s_expm1f.c @@ -1,122 +1,121 @@ /* s_expm1f.c -- float version of s_expm1.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" static const float one = 1.0, tiny = 1.0e-30, o_threshold = 8.8721679688e+01,/* 0x42b17180 */ ln2_hi = 6.9313812256e-01,/* 0x3f317180 */ ln2_lo = 9.0580006145e-06,/* 0x3717f7d1 */ invln2 = 1.4426950216e+00,/* 0x3fb8aa3b */ /* * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]: * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04 * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c): */ Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */ Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */ static volatile float huge = 1.0e+30; float expm1f(float x) { float y,hi,lo,c,t,e,hxs,hfx,r1,twopk; int32_t k,xsb; u_int32_t hx; GET_FLOAT_WORD(hx,x); xsb = hx&0x80000000; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out huge and non-finite argument */ if(hx >= 0x4195b844) { /* if |x|>=27*ln2 */ if(hx >= 0x42b17218) { /* if |x|>=88.721... */ if(hx>0x7f800000) return x+x; /* NaN */ if(hx==0x7f800000) return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ if(x > o_threshold) return huge*huge; /* overflow */ } if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */ if(x+tiny<(float)0.0) /* raise inexact */ return tiny-one; /* return -1 */ } } /* argument reduction */ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ if(xsb==0) {hi = x - ln2_hi; lo = ln2_lo; k = 1;} else {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} } else { k = invln2*x+((xsb==0)?(float)0.5:(float)-0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } STRICT_ASSIGN(float, x, hi - lo); c = (hi-x)-lo; } else if(hx < 0x33000000) { /* when |x|<2**-25, return x */ t = huge+x; /* return x with inexact flags when x!=0 */ return x - (t-(huge+x)); } else k = 0; /* x is now in primary range */ hfx = (float)0.5*x; hxs = x*hfx; r1 = one+hxs*(Q1+hxs*Q2); t = (float)3.0-r1*hfx; e = hxs*((r1-t)/((float)6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+k))<<23); /* 2^k */ e = (x*(e-c)-c); e -= hxs; if(k== -1) return (float)0.5*(x-e)-(float)0.5; if(k==1) { if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5)); else return one+(float)2.0*(x-e); } if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ y = one-(e-x); if (k == 128) y = y*2.0F*0x1p127F; else y = y*twopk; return y-one; } t = one; if(k<23) { SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */ y = t-(e-x); y = y*twopk; } else { SET_FLOAT_WORD(t,((0x7f-k)<<23)); /* 2^-k */ y = x-(e+t); y += one; y = y*twopk; } } return y; } diff --git a/lib/msun/src/s_fabs.c b/lib/msun/src/s_fabs.c index ec071d481ac6..d9e7ffb5d6bd 100644 --- a/lib/msun/src/s_fabs.c +++ b/lib/msun/src/s_fabs.c @@ -1,28 +1,27 @@ /* @(#)s_fabs.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * fabs(x) returns the absolute value of x. */ #include "math.h" #include "math_private.h" double fabs(double x) { u_int32_t high; GET_HIGH_WORD(high,x); SET_HIGH_WORD(x,high&0x7fffffff); return x; } diff --git a/lib/msun/src/s_fabsf.c b/lib/msun/src/s_fabsf.c index 501676253385..66d09534dbc5 100644 --- a/lib/msun/src/s_fabsf.c +++ b/lib/msun/src/s_fabsf.c @@ -1,31 +1,30 @@ /* s_fabsf.c -- float version of s_fabs.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * fabsf(x) returns the absolute value of x. */ #include "math.h" #include "math_private.h" float fabsf(float x) { u_int32_t ix; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x7fffffff); return x; } diff --git a/lib/msun/src/s_fdim.c b/lib/msun/src/s_fdim.c index 580ab4605f92..4f56ee4b3482 100644 --- a/lib/msun/src/s_fdim.c +++ b/lib/msun/src/s_fdim.c @@ -1,46 +1,45 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #define DECL(type, fn) \ type \ fn(type x, type y) \ { \ \ if (isnan(x)) \ return (x); \ if (isnan(y)) \ return (y); \ return (x > y ? x - y : 0.0); \ } DECL(double, fdim) DECL(float, fdimf) DECL(long double, fdiml) diff --git a/lib/msun/src/s_finite.c b/lib/msun/src/s_finite.c index c6b1cfa6d111..e4df716e4653 100644 --- a/lib/msun/src/s_finite.c +++ b/lib/msun/src/s_finite.c @@ -1,27 +1,26 @@ /* @(#)s_finite.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * finite(x) returns 1 is x is finite, else 0; * no branching! */ #include "math.h" #include "math_private.h" int finite(double x) { int32_t hx; GET_HIGH_WORD(hx,x); return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31); } diff --git a/lib/msun/src/s_finitef.c b/lib/msun/src/s_finitef.c index 94e527257c06..9a4a876a791f 100644 --- a/lib/msun/src/s_finitef.c +++ b/lib/msun/src/s_finitef.c @@ -1,30 +1,29 @@ /* s_finitef.c -- float version of s_finite.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * finitef(x) returns 1 is x is finite, else 0; * no branching! */ #include "math.h" #include "math_private.h" int finitef(float x) { int32_t ix; GET_FLOAT_WORD(ix,x); return (int)((u_int32_t)((ix&0x7fffffff)-0x7f800000)>>31); } diff --git a/lib/msun/src/s_floor.c b/lib/msun/src/s_floor.c index 1746cf27f016..bccefa7a2d49 100644 --- a/lib/msun/src/s_floor.c +++ b/lib/msun/src/s_floor.c @@ -1,76 +1,75 @@ /* @(#)s_floor.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * floor(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to floor(x). */ #include #include "math.h" #include "math_private.h" static const double huge = 1.0e300; double floor(double x) { int32_t i0,i1,j0; u_int32_t i,j; EXTRACT_WORDS(i0,i1,x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ if(i0>=0) {i0=i1=0;} else if(((i0&0x7fffffff)|i1)!=0) { i0=0xbff00000;i1=0;} } } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0<0) i0 += (0x00100000)>>j0; i0 &= (~i); i1=0; } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((u_int32_t)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0<0) { if(j0==20) i0+=1; else { j = i1+(1<<(52-j0)); if(j /* * floorf(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to floorf(x). */ #include "math.h" #include "math_private.h" static const float huge = 1.0e30; float floorf(float x) { int32_t i0,j0; u_int32_t i; GET_FLOAT_WORD(i0,x); j0 = ((i0>>23)&0xff)-0x7f; if(j0<23) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ if(i0>=0) {i0=0;} else if((i0&0x7fffffff)!=0) { i0=0xbf800000;} } } else { i = (0x007fffff)>>j0; if((i0&i)==0) return x; /* x is integral */ if(huge+x>(float)0.0) { /* raise inexact flag */ if(i0<0) i0 += (0x00800000)>>j0; i0 &= (~i); } } } else { if(j0==0x80) return x+x; /* inf or NaN */ else return x; /* x is integral */ } SET_FLOAT_WORD(x,i0); return x; } diff --git a/lib/msun/src/s_floorl.c b/lib/msun/src/s_floorl.c index ee9a391ffe41..7c4464b21abe 100644 --- a/lib/msun/src/s_floorl.c +++ b/lib/msun/src/s_floorl.c @@ -1,99 +1,98 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * From: @(#)s_floor.c 5.1 93/09/24 */ -#include /* * floorl(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to floorl(x). */ #include #include #include #include "fpmath.h" #ifdef LDBL_IMPLICIT_NBIT #define MANH_SIZE (LDBL_MANH_SIZE + 1) #define INC_MANH(u, c) do { \ uint64_t o = u.bits.manh; \ u.bits.manh += (c); \ if (u.bits.manh < o) \ u.bits.exp++; \ } while (0) #else #define MANH_SIZE LDBL_MANH_SIZE #define INC_MANH(u, c) do { \ uint64_t o = u.bits.manh; \ u.bits.manh += (c); \ if (u.bits.manh < o) { \ u.bits.exp++; \ u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \ } \ } while (0) #endif static const long double huge = 1.0e300; long double floorl(long double x) { union IEEEl2bits u = { .e = x }; int e = u.bits.exp - LDBL_MAX_EXP + 1; if (e < MANH_SIZE - 1) { if (e < 0) { /* raise inexact if x != 0 */ if (huge + x > 0.0) if (u.bits.exp > 0 || (u.bits.manh | u.bits.manl) != 0) u.e = u.bits.sign ? -1.0 : 0.0; } else { uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); if (((u.bits.manh & m) | u.bits.manl) == 0) return (x); /* x is integral */ if (u.bits.sign) { #ifdef LDBL_IMPLICIT_NBIT if (e == 0) u.bits.exp++; else #endif INC_MANH(u, 1llu << (MANH_SIZE - e - 1)); } if (huge + x > 0.0) { /* raise inexact flag */ u.bits.manh &= ~m; u.bits.manl = 0; } } } else if (e < LDBL_MANT_DIG - 1) { uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); if ((u.bits.manl & m) == 0) return (x); /* x is integral */ if (u.bits.sign) { if (e == MANH_SIZE - 1) INC_MANH(u, 1); else { uint64_t o = u.bits.manl; u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1); if (u.bits.manl < o) /* got a carry */ INC_MANH(u, 1); } } if (huge + x > 0.0) /* raise inexact flag */ u.bits.manl &= ~m; } return (u.e); } diff --git a/lib/msun/src/s_fma.c b/lib/msun/src/s_fma.c index 0788bb2d47e8..b8a342646d85 100644 --- a/lib/msun/src/s_fma.c +++ b/lib/msun/src/s_fma.c @@ -1,296 +1,295 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "math_private.h" #ifdef USE_BUILTIN_FMA double fma(double x, double y, double z) { return (__builtin_fma(x, y, z)); } #else /* * A struct dd represents a floating-point number with twice the precision * of a double. We maintain the invariant that "hi" stores the 53 high-order * bits of the result. */ struct dd { double hi; double lo; }; /* * Compute a+b exactly, returning the exact result in a struct dd. We assume * that both a and b are finite, but make no assumptions about their relative * magnitudes. */ static inline struct dd dd_add(double a, double b) { struct dd ret; double s; ret.hi = a + b; s = ret.hi - a; ret.lo = (a - (ret.hi - s)) + (b - s); return (ret); } /* * Compute a+b, with a small tweak: The least significant bit of the * result is adjusted into a sticky bit summarizing all the bits that * were lost to rounding. This adjustment negates the effects of double * rounding when the result is added to another number with a higher * exponent. For an explanation of round and sticky bits, see any reference * on FPU design, e.g., * * J. Coonen. An Implementation Guide to a Proposed Standard for * Floating-Point Arithmetic. Computer, vol. 13, no. 1, Jan 1980. */ static inline double add_adjusted(double a, double b) { struct dd sum; uint64_t hibits, lobits; sum = dd_add(a, b); if (sum.lo != 0) { EXTRACT_WORD64(hibits, sum.hi); if ((hibits & 1) == 0) { /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */ EXTRACT_WORD64(lobits, sum.lo); hibits += 1 - ((hibits ^ lobits) >> 62); INSERT_WORD64(sum.hi, hibits); } } return (sum.hi); } /* * Compute ldexp(a+b, scale) with a single rounding error. It is assumed * that the result will be subnormal, and care is taken to ensure that * double rounding does not occur. */ static inline double add_and_denormalize(double a, double b, int scale) { struct dd sum; uint64_t hibits, lobits; int bits_lost; sum = dd_add(a, b); /* * If we are losing at least two bits of accuracy to denormalization, * then the first lost bit becomes a round bit, and we adjust the * lowest bit of sum.hi to make it a sticky bit summarizing all the * bits in sum.lo. With the sticky bit adjusted, the hardware will * break any ties in the correct direction. * * If we are losing only one bit to denormalization, however, we must * break the ties manually. */ if (sum.lo != 0) { EXTRACT_WORD64(hibits, sum.hi); bits_lost = -((int)(hibits >> 52) & 0x7ff) - scale + 1; if ((bits_lost != 1) ^ (int)(hibits & 1)) { /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */ EXTRACT_WORD64(lobits, sum.lo); hibits += 1 - (((hibits ^ lobits) >> 62) & 2); INSERT_WORD64(sum.hi, hibits); } } return (ldexp(sum.hi, scale)); } /* * Compute a*b exactly, returning the exact result in a struct dd. We assume * that both a and b are normalized, so no underflow or overflow will occur. * The current rounding mode must be round-to-nearest. */ static inline struct dd dd_mul(double a, double b) { static const double split = 0x1p27 + 1.0; struct dd ret; double ha, hb, la, lb, p, q; p = a * split; ha = a - p; ha += p; la = a - ha; p = b * split; hb = b - p; hb += p; lb = b - hb; p = ha * hb; q = ha * lb + la * hb; ret.hi = p + q; ret.lo = p - ret.hi + q + la * lb; return (ret); } /* * Fused multiply-add: Compute x * y + z with a single rounding error. * * We use scaling to avoid overflow/underflow, along with the * canonical precision-doubling technique adapted from: * * Dekker, T. A Floating-Point Technique for Extending the * Available Precision. Numer. Math. 18, 224-242 (1971). * * This algorithm is sensitive to the rounding precision. FPUs such * as the i387 must be set in double-precision mode if variables are * to be stored in FP registers in order to avoid incorrect results. * This is the default on FreeBSD, but not on many other systems. * * Hardware instructions should be used on architectures that support it, * since this implementation will likely be several times slower. */ double fma(double x, double y, double z) { double xs, ys, zs, adj; struct dd xy, r; int oround; int ex, ey, ez; int spread; /* * Handle special cases. The order of operations and the particular * return values here are crucial in handling special cases involving * infinities, NaNs, overflows, and signed zeroes correctly. */ if (x == 0.0 || y == 0.0) return (x * y + z); if (z == 0.0) return (x * y); if (!isfinite(x) || !isfinite(y)) return (x * y + z); if (!isfinite(z)) return (z); xs = frexp(x, &ex); ys = frexp(y, &ey); zs = frexp(z, &ez); oround = fegetround(); spread = ex + ey - ez; /* * If x * y and z are many orders of magnitude apart, the scaling * will overflow, so we handle these cases specially. Rounding * modes other than FE_TONEAREST are painful. */ if (spread < -DBL_MANT_DIG) { feraiseexcept(FE_INEXACT); if (!isnormal(z)) feraiseexcept(FE_UNDERFLOW); switch (oround) { case FE_TONEAREST: return (z); case FE_TOWARDZERO: if (x > 0.0 ^ y < 0.0 ^ z < 0.0) return (z); else return (nextafter(z, 0)); case FE_DOWNWARD: if (x > 0.0 ^ y < 0.0) return (z); else return (nextafter(z, -INFINITY)); default: /* FE_UPWARD */ if (x > 0.0 ^ y < 0.0) return (nextafter(z, INFINITY)); else return (z); } } if (spread <= DBL_MANT_DIG * 2) zs = ldexp(zs, -spread); else zs = copysign(DBL_MIN, zs); fesetround(FE_TONEAREST); /* work around clang bug 8100 */ volatile double vxs = xs; /* * Basic approach for round-to-nearest: * * (xy.hi, xy.lo) = x * y (exact) * (r.hi, r.lo) = xy.hi + z (exact) * adj = xy.lo + r.lo (inexact; low bit is sticky) * result = r.hi + adj (correctly rounded) */ xy = dd_mul(vxs, ys); r = dd_add(xy.hi, zs); spread = ex + ey; if (r.hi == 0.0) { /* * When the addends cancel to 0, ensure that the result has * the correct sign. */ fesetround(oround); volatile double vzs = zs; /* XXX gcc CSE bug workaround */ return (xy.hi + vzs + ldexp(xy.lo, spread)); } if (oround != FE_TONEAREST) { /* * There is no need to worry about double rounding in directed * rounding modes. */ fesetround(oround); /* work around clang bug 8100 */ volatile double vrlo = r.lo; adj = vrlo + xy.lo; return (ldexp(r.hi + adj, spread)); } adj = add_adjusted(r.lo, xy.lo); if (spread + ilogb(r.hi) > -1023) return (ldexp(r.hi + adj, spread)); else return (add_and_denormalize(r.hi, adj, spread)); } #endif /* !USE_BUILTIN_FMA */ #if (LDBL_MANT_DIG == 53) __weak_reference(fma, fmal); #endif diff --git a/lib/msun/src/s_fmaf.c b/lib/msun/src/s_fmaf.c index c433f523fe08..5f3d5d1b1b99 100644 --- a/lib/msun/src/s_fmaf.c +++ b/lib/msun/src/s_fmaf.c @@ -1,77 +1,76 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" #ifdef USE_BUILTIN_FMAF float fmaf(float x, float y, float z) { return (__builtin_fmaf(x, y, z)); } #else /* * Fused multiply-add: Compute x * y + z with a single rounding error. * * A double has more than twice as much precision than a float, so * direct double-precision arithmetic suffices, except where double * rounding occurs. */ float fmaf(float x, float y, float z) { double xy, result; uint32_t hr, lr; xy = (double)x * y; result = xy + z; EXTRACT_WORDS(hr, lr, result); /* Common case: The double precision result is fine. */ if ((lr & 0x1fffffff) != 0x10000000 || /* not a halfway case */ (hr & 0x7ff00000) == 0x7ff00000 || /* NaN */ result - xy == z || /* exact */ fegetround() != FE_TONEAREST) /* not round-to-nearest */ return (result); /* * If result is inexact, and exactly halfway between two float values, * we need to adjust the low-order bit in the direction of the error. */ fesetround(FE_TOWARDZERO); volatile double vxy = xy; /* XXX work around gcc CSE bug */ double adjusted_result = vxy + z; fesetround(FE_TONEAREST); if (result == adjusted_result) SET_LOW_WORD(adjusted_result, lr + 1); return (adjusted_result); } #endif /* !USE_BUILTIN_FMAF */ diff --git a/lib/msun/src/s_fmal.c b/lib/msun/src/s_fmal.c index 0d5e2c0bc98f..3d333632127c 100644 --- a/lib/msun/src/s_fmal.c +++ b/lib/msun/src/s_fmal.c @@ -1,272 +1,271 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include "fpmath.h" /* * A struct dd represents a floating-point number with twice the precision * of a long double. We maintain the invariant that "hi" stores the high-order * bits of the result. */ struct dd { long double hi; long double lo; }; /* * Compute a+b exactly, returning the exact result in a struct dd. We assume * that both a and b are finite, but make no assumptions about their relative * magnitudes. */ static inline struct dd dd_add(long double a, long double b) { struct dd ret; long double s; ret.hi = a + b; s = ret.hi - a; ret.lo = (a - (ret.hi - s)) + (b - s); return (ret); } /* * Compute a+b, with a small tweak: The least significant bit of the * result is adjusted into a sticky bit summarizing all the bits that * were lost to rounding. This adjustment negates the effects of double * rounding when the result is added to another number with a higher * exponent. For an explanation of round and sticky bits, see any reference * on FPU design, e.g., * * J. Coonen. An Implementation Guide to a Proposed Standard for * Floating-Point Arithmetic. Computer, vol. 13, no. 1, Jan 1980. */ static inline long double add_adjusted(long double a, long double b) { struct dd sum; union IEEEl2bits u; sum = dd_add(a, b); if (sum.lo != 0) { u.e = sum.hi; if ((u.bits.manl & 1) == 0) sum.hi = nextafterl(sum.hi, INFINITY * sum.lo); } return (sum.hi); } /* * Compute ldexp(a+b, scale) with a single rounding error. It is assumed * that the result will be subnormal, and care is taken to ensure that * double rounding does not occur. */ static inline long double add_and_denormalize(long double a, long double b, int scale) { struct dd sum; int bits_lost; union IEEEl2bits u; sum = dd_add(a, b); /* * If we are losing at least two bits of accuracy to denormalization, * then the first lost bit becomes a round bit, and we adjust the * lowest bit of sum.hi to make it a sticky bit summarizing all the * bits in sum.lo. With the sticky bit adjusted, the hardware will * break any ties in the correct direction. * * If we are losing only one bit to denormalization, however, we must * break the ties manually. */ if (sum.lo != 0) { u.e = sum.hi; bits_lost = -u.bits.exp - scale + 1; if ((bits_lost != 1) ^ (int)(u.bits.manl & 1)) sum.hi = nextafterl(sum.hi, INFINITY * sum.lo); } return (ldexp(sum.hi, scale)); } /* * Compute a*b exactly, returning the exact result in a struct dd. We assume * that both a and b are normalized, so no underflow or overflow will occur. * The current rounding mode must be round-to-nearest. */ static inline struct dd dd_mul(long double a, long double b) { #if LDBL_MANT_DIG == 64 static const long double split = 0x1p32L + 1.0; #elif LDBL_MANT_DIG == 113 static const long double split = 0x1p57L + 1.0; #endif struct dd ret; long double ha, hb, la, lb, p, q; p = a * split; ha = a - p; ha += p; la = a - ha; p = b * split; hb = b - p; hb += p; lb = b - hb; p = ha * hb; q = ha * lb + la * hb; ret.hi = p + q; ret.lo = p - ret.hi + q + la * lb; return (ret); } /* * Fused multiply-add: Compute x * y + z with a single rounding error. * * We use scaling to avoid overflow/underflow, along with the * canonical precision-doubling technique adapted from: * * Dekker, T. A Floating-Point Technique for Extending the * Available Precision. Numer. Math. 18, 224-242 (1971). */ long double fmal(long double x, long double y, long double z) { long double xs, ys, zs, adj; struct dd xy, r; int oround; int ex, ey, ez; int spread; /* * Handle special cases. The order of operations and the particular * return values here are crucial in handling special cases involving * infinities, NaNs, overflows, and signed zeroes correctly. */ if (x == 0.0 || y == 0.0) return (x * y + z); if (z == 0.0) return (x * y); if (!isfinite(x) || !isfinite(y)) return (x * y + z); if (!isfinite(z)) return (z); xs = frexpl(x, &ex); ys = frexpl(y, &ey); zs = frexpl(z, &ez); oround = fegetround(); spread = ex + ey - ez; /* * If x * y and z are many orders of magnitude apart, the scaling * will overflow, so we handle these cases specially. Rounding * modes other than FE_TONEAREST are painful. */ if (spread < -LDBL_MANT_DIG) { feraiseexcept(FE_INEXACT); if (!isnormal(z)) feraiseexcept(FE_UNDERFLOW); switch (oround) { case FE_TONEAREST: return (z); case FE_TOWARDZERO: if (x > 0.0 ^ y < 0.0 ^ z < 0.0) return (z); else return (nextafterl(z, 0)); case FE_DOWNWARD: if (x > 0.0 ^ y < 0.0) return (z); else return (nextafterl(z, -INFINITY)); default: /* FE_UPWARD */ if (x > 0.0 ^ y < 0.0) return (nextafterl(z, INFINITY)); else return (z); } } if (spread <= LDBL_MANT_DIG * 2) zs = ldexpl(zs, -spread); else zs = copysignl(LDBL_MIN, zs); fesetround(FE_TONEAREST); /* work around clang bug 8100 */ volatile long double vxs = xs; /* * Basic approach for round-to-nearest: * * (xy.hi, xy.lo) = x * y (exact) * (r.hi, r.lo) = xy.hi + z (exact) * adj = xy.lo + r.lo (inexact; low bit is sticky) * result = r.hi + adj (correctly rounded) */ xy = dd_mul(vxs, ys); r = dd_add(xy.hi, zs); spread = ex + ey; if (r.hi == 0.0) { /* * When the addends cancel to 0, ensure that the result has * the correct sign. */ fesetround(oround); volatile long double vzs = zs; /* XXX gcc CSE bug workaround */ return (xy.hi + vzs + ldexpl(xy.lo, spread)); } if (oround != FE_TONEAREST) { /* * There is no need to worry about double rounding in directed * rounding modes. */ fesetround(oround); /* work around clang bug 8100 */ volatile long double vrlo = r.lo; adj = vrlo + xy.lo; return (ldexpl(r.hi + adj, spread)); } adj = add_adjusted(r.lo, xy.lo); if (spread + ilogbl(r.hi) > -16383) return (ldexpl(r.hi + adj, spread)); else return (add_and_denormalize(r.hi, adj, spread)); } diff --git a/lib/msun/src/s_fmax.c b/lib/msun/src/s_fmax.c index aca4e0585cdd..5d437fcefc9b 100644 --- a/lib/msun/src/s_fmax.c +++ b/lib/msun/src/s_fmax.c @@ -1,66 +1,65 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #ifdef USE_BUILTIN_FMAX double fmax(double x, double y) { return (__builtin_fmax(x, y)); } #else double fmax(double x, double y) { union IEEEd2bits u[2]; u[0].d = x; u[1].d = y; /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0) return (y); if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[u[0].bits.sign].d); return (x > y ? x : y); } #endif #if (LDBL_MANT_DIG == 53) __weak_reference(fmax, fmaxl); #endif diff --git a/lib/msun/src/s_fmaxf.c b/lib/msun/src/s_fmaxf.c index 8684fb6bb68c..1572572e43a6 100644 --- a/lib/msun/src/s_fmaxf.c +++ b/lib/msun/src/s_fmaxf.c @@ -1,61 +1,60 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "fpmath.h" #ifdef USE_BUILTIN_FMAXF float fmaxf(float x, float y) { return (__builtin_fmaxf(x, y)); } #else float fmaxf(float x, float y) { union IEEEf2bits u[2]; u[0].f = x; u[1].f = y; /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 255 && u[0].bits.man != 0) return (y); if (u[1].bits.exp == 255 && u[1].bits.man != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[u[0].bits.sign].f); return (x > y ? x : y); } #endif diff --git a/lib/msun/src/s_fmaxl.c b/lib/msun/src/s_fmaxl.c index d0c1a806bdaf..73e2a4bb19fd 100644 --- a/lib/msun/src/s_fmaxl.c +++ b/lib/msun/src/s_fmaxl.c @@ -1,55 +1,54 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "fpmath.h" long double fmaxl(long double x, long double y) { union IEEEl2bits u[2]; u[0].e = x; mask_nbit_l(u[0]); u[1].e = y; mask_nbit_l(u[1]); /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0) return (y); if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[0].bits.sign ? y : x); return (x > y ? x : y); } diff --git a/lib/msun/src/s_fmin.c b/lib/msun/src/s_fmin.c index aa67d161ec34..a349e5ddaf0e 100644 --- a/lib/msun/src/s_fmin.c +++ b/lib/msun/src/s_fmin.c @@ -1,66 +1,65 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #ifdef USE_BUILTIN_FMIN double fmin(double x, double y) { return (__builtin_fmin(x, y)); } #else double fmin(double x, double y) { union IEEEd2bits u[2]; u[0].d = x; u[1].d = y; /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0) return (y); if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[u[1].bits.sign].d); return (x < y ? x : y); } #endif #if (LDBL_MANT_DIG == 53) __weak_reference(fmin, fminl); #endif diff --git a/lib/msun/src/s_fminf.c b/lib/msun/src/s_fminf.c index 01e52d9becdc..5c2537e32d25 100644 --- a/lib/msun/src/s_fminf.c +++ b/lib/msun/src/s_fminf.c @@ -1,61 +1,60 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "fpmath.h" #ifdef USE_BUILTIN_FMINF float fminf(float x, float y) { return (__builtin_fminf(x, y)); } #else float fminf(float x, float y) { union IEEEf2bits u[2]; u[0].f = x; u[1].f = y; /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 255 && u[0].bits.man != 0) return (y); if (u[1].bits.exp == 255 && u[1].bits.man != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[u[1].bits.sign].f); return (x < y ? x : y); } #endif diff --git a/lib/msun/src/s_fminl.c b/lib/msun/src/s_fminl.c index f79a08d6c774..7ac17e313440 100644 --- a/lib/msun/src/s_fminl.c +++ b/lib/msun/src/s_fminl.c @@ -1,55 +1,54 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include "fpmath.h" long double fminl(long double x, long double y) { union IEEEl2bits u[2]; u[0].e = x; mask_nbit_l(u[0]); u[1].e = y; mask_nbit_l(u[1]); /* Check for NaNs to avoid raising spurious exceptions. */ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0) return (y); if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0) return (x); /* Handle comparisons of signed zeroes. */ if (u[0].bits.sign != u[1].bits.sign) return (u[1].bits.sign ? y : x); return (x < y ? x : y); } diff --git a/lib/msun/src/s_frexp.c b/lib/msun/src/s_frexp.c index ee234d247300..468a05853007 100644 --- a/lib/msun/src/s_frexp.c +++ b/lib/msun/src/s_frexp.c @@ -1,54 +1,53 @@ /* @(#)s_frexp.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * for non-zero x * x = frexp(arg,&exp); * return a double fp quantity x such that 0.5 <= |x| <1.0 * and the corresponding binary exponent "exp". That is * arg = x*2^exp. * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg * with *exp=0. */ #include #include "math.h" #include "math_private.h" static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ double frexp(double x, int *eptr) { int32_t hx, ix, lx; EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; *eptr = 0; if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ if (ix<0x00100000) { /* subnormal */ x *= two54; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; *eptr = -54; } *eptr += (ix>>20)-1022; hx = (hx&0x800fffff)|0x3fe00000; SET_HIGH_WORD(x,hx); return x; } #if (LDBL_MANT_DIG == 53) __weak_reference(frexp, frexpl); #endif diff --git a/lib/msun/src/s_frexpf.c b/lib/msun/src/s_frexpf.c index 6b39e6ff8b2b..bca27b5147d8 100644 --- a/lib/msun/src/s_frexpf.c +++ b/lib/msun/src/s_frexpf.c @@ -1,41 +1,40 @@ /* s_frexpf.c -- float version of s_frexp.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float two25 = 3.3554432000e+07; /* 0x4c000000 */ float frexpf(float x, int *eptr) { int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; *eptr = 0; if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */ if (ix<0x00800000) { /* subnormal */ x *= two25; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; *eptr = -25; } *eptr += (ix>>23)-126; hx = (hx&0x807fffff)|0x3f000000; SET_FLOAT_WORD(x,hx); return x; } diff --git a/lib/msun/src/s_ilogb.c b/lib/msun/src/s_ilogb.c index 0b076edbd9b5..ac9feceaf14e 100644 --- a/lib/msun/src/s_ilogb.c +++ b/lib/msun/src/s_ilogb.c @@ -1,46 +1,45 @@ /* @(#)s_ilogb.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* ilogb(double x) * return the binary exponent of non-zero x * ilogb(0) = FP_ILOGB0 * ilogb(NaN) = FP_ILOGBNAN (no signal is raised) * ilogb(inf) = INT_MAX (no signal is raised) */ #include #include "math.h" #include "math_private.h" int ilogb(double x) { int32_t hx,lx,ix; EXTRACT_WORDS(hx,lx,x); hx &= 0x7fffffff; if(hx<0x00100000) { if((hx|lx)==0) return FP_ILOGB0; else /* subnormal x */ if(hx==0) { for (ix = -1043; lx>0; lx<<=1) ix -=1; } else { for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; } return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; else if (hx>0x7ff00000 || lx!=0) return FP_ILOGBNAN; else return INT_MAX; } diff --git a/lib/msun/src/s_ilogbf.c b/lib/msun/src/s_ilogbf.c index ff3df1fc5b90..e0f8fee26ac8 100644 --- a/lib/msun/src/s_ilogbf.c +++ b/lib/msun/src/s_ilogbf.c @@ -1,38 +1,37 @@ /* s_ilogbf.c -- float version of s_ilogb.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" int ilogbf(float x) { int32_t hx,ix; GET_FLOAT_WORD(hx,x); hx &= 0x7fffffff; if(hx<0x00800000) { if(hx==0) return FP_ILOGB0; else /* subnormal x */ for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1; return ix; } else if (hx<0x7f800000) return (hx>>23)-127; else if (hx>0x7f800000) return FP_ILOGBNAN; else return INT_MAX; } diff --git a/lib/msun/src/s_ilogbl.c b/lib/msun/src/s_ilogbl.c index f45cd7b67159..ea0d11b8aca9 100644 --- a/lib/msun/src/s_ilogbl.c +++ b/lib/msun/src/s_ilogbl.c @@ -1,51 +1,50 @@ /* * From: @(#)s_ilogb.c 5.1 93/09/24 * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include #include #include "fpmath.h" int ilogbl(long double x) { union IEEEl2bits u; unsigned long m; int b; u.e = x; if (u.bits.exp == 0) { if ((u.bits.manl | u.bits.manh) == 0) return (FP_ILOGB0); /* denormalized */ if (u.bits.manh == 0) { m = 1lu << (LDBL_MANL_SIZE - 1); for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1) b++; } else { m = 1lu << (LDBL_MANH_SIZE - 1); for (b = 0; !(u.bits.manh & m); m >>= 1) b++; } #ifdef LDBL_IMPLICIT_NBIT b++; #endif return (LDBL_MIN_EXP - b - 1); } else if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1) return (u.bits.exp - LDBL_MAX_EXP + 1); else if (u.bits.manl != 0 || u.bits.manh != 0) return (FP_ILOGBNAN); else return (INT_MAX); } diff --git a/lib/msun/src/s_llrint.c b/lib/msun/src/s_llrint.c index 460c4a07d5e3..5e2760381b8c 100644 --- a/lib/msun/src/s_llrint.c +++ b/lib/msun/src/s_llrint.c @@ -1,7 +1,6 @@ -#include #define type double #define roundit rint #define dtype long long #define fn llrint #include "s_lrint.c" diff --git a/lib/msun/src/s_llrintf.c b/lib/msun/src/s_llrintf.c index 3ed16799f47f..b117f7c99dbc 100644 --- a/lib/msun/src/s_llrintf.c +++ b/lib/msun/src/s_llrintf.c @@ -1,7 +1,6 @@ -#include #define type float #define roundit rintf #define dtype long long #define fn llrintf #include "s_lrint.c" diff --git a/lib/msun/src/s_llrintl.c b/lib/msun/src/s_llrintl.c index fed23f32fd6f..82f4529dc815 100644 --- a/lib/msun/src/s_llrintl.c +++ b/lib/msun/src/s_llrintl.c @@ -1,7 +1,6 @@ -#include #define type long double #define roundit rintl #define dtype long long #define fn llrintl #include "s_lrint.c" diff --git a/lib/msun/src/s_llround.c b/lib/msun/src/s_llround.c index f8e76134b654..3983ce1edfca 100644 --- a/lib/msun/src/s_llround.c +++ b/lib/msun/src/s_llround.c @@ -1,9 +1,8 @@ -#include #define type double #define roundit round #define dtype long long #define DTYPE_MIN LLONG_MIN #define DTYPE_MAX LLONG_MAX #define fn llround #include "s_lround.c" diff --git a/lib/msun/src/s_llroundf.c b/lib/msun/src/s_llroundf.c index 753fd96265aa..827d915ded9b 100644 --- a/lib/msun/src/s_llroundf.c +++ b/lib/msun/src/s_llroundf.c @@ -1,9 +1,8 @@ -#include #define type float #define roundit roundf #define dtype long long #define DTYPE_MIN LLONG_MIN #define DTYPE_MAX LLONG_MAX #define fn llroundf #include "s_lround.c" diff --git a/lib/msun/src/s_llroundl.c b/lib/msun/src/s_llroundl.c index b5a97d97f2ae..40cad84c56f5 100644 --- a/lib/msun/src/s_llroundl.c +++ b/lib/msun/src/s_llroundl.c @@ -1,9 +1,8 @@ -#include #define type long double #define roundit roundl #define dtype long long #define DTYPE_MIN LLONG_MIN #define DTYPE_MAX LLONG_MAX #define fn llroundl #include "s_lround.c" diff --git a/lib/msun/src/s_log1p.c b/lib/msun/src/s_log1p.c index 61b03f00f33b..969715f90f05 100644 --- a/lib/msun/src/s_log1p.c +++ b/lib/msun/src/s_log1p.c @@ -1,178 +1,177 @@ /* @(#)s_log1p.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* double log1p(double x) * * Method : * 1. Argument Reduction: find k and f such that * 1+x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * Note. If k=0, then f=x is exact. However, if k!=0, then f * may not be representable exactly. In that case, a correction * term is need. Let u=1+x rounded. Let c = (1+x)-u, then * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), * and add back the correction term c/u. * (Note: when x > 2**53, one can simply return log(x)) * * 2. Approximation of log1p(f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Reme algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s * (the values of Lp1 to Lp7 are listed in the program) * and * | 2 14 | -58.45 * | Lp1*s +...+Lp7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log1p(f) = f - (hfsq - s*(hfsq+R)). * * 3. Finally, log1p(x) = k*ln2 + log1p(f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log1p(x) is NaN with signal if x < -1 (including -INF) ; * log1p(+INF) is +INF; log1p(-1) is -INF with signal; * log1p(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. * * Note: Assuming log() return accurate answer, the following * algorithm can be used to compute log1p(x) to within a few ULP: * * u = 1+x; * if(u==1.0) return x ; else * return log(u)*(x/(u-1.0)); * * See HP-15C Advanced Functions Handbook, p.193. */ #include #include "math.h" #include "math_private.h" static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ static const double zero = 0.0; static volatile double vzero = 0.0; double log1p(double x) { double hfsq,f,c,s,z,R,u; int32_t k,hx,hu,ax; GET_HIGH_WORD(hx,x); ax = hx&0x7fffffff; k = 1; if (hx < 0x3FDA827A) { /* 1+x < sqrt(2)+ */ if(ax>=0x3ff00000) { /* x <= -1.0 */ if(x==-1.0) return -two54/vzero; /* log1p(-1)=+inf */ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ } if(ax<0x3e200000) { /* |x| < 2**-29 */ if(two54+x>zero /* raise inexact */ &&ax<0x3c900000) /* |x| < 2**-54 */ return x; else return x - x*x*0.5; } if(hx>0||hx<=((int32_t)0xbfd2bec4)) { k=0;f=x;hu=1;} /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ } if (hx >= 0x7ff00000) return x+x; if(k!=0) { if(hx<0x43400000) { STRICT_ASSIGN(double,u,1.0+x); GET_HIGH_WORD(hu,u); k = (hu>>20)-1023; c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ c /= u; } else { u = x; GET_HIGH_WORD(hu,u); k = (hu>>20)-1023; c = 0; } hu &= 0x000fffff; /* * The approximation to sqrt(2) used in thresholds is not * critical. However, the ones used above must give less * strict bounds than the one here so that the k==0 case is * never reached from here, since here we have committed to * using the correction term but don't use it if k==0. */ if(hu<0x6a09e) { /* u ~< sqrt(2) */ SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */ } else { k += 1; SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */ hu = (0x00100000-hu)>>2; } f = u-1.0; } hfsq=0.5*f*f; if(hu==0) { /* |f| < 2**-20 */ if(f==zero) { if(k==0) { return zero; } else { c += k*ln2_lo; return k*ln2_hi+c; } } R = hfsq*(1.0-0.66666666666666666*f); if(k==0) return f-R; else return k*ln2_hi-((R-(k*ln2_lo+c))-f); } s = f/(2.0+f); z = s*s; R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); if(k==0) return f-(hfsq-s*(hfsq+R)); else return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); } #if (LDBL_MANT_DIG == 53) __weak_reference(log1p, log1pl); #endif diff --git a/lib/msun/src/s_log1pf.c b/lib/msun/src/s_log1pf.c index d53fc7144e1d..dad567b58573 100644 --- a/lib/msun/src/s_log1pf.c +++ b/lib/msun/src/s_log1pf.c @@ -1,113 +1,112 @@ /* s_log1pf.c -- float version of s_log1p.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ two25 = 3.355443200e+07, /* 0x4c000000 */ Lp1 = 6.6666668653e-01, /* 3F2AAAAB */ Lp2 = 4.0000000596e-01, /* 3ECCCCCD */ Lp3 = 2.8571429849e-01, /* 3E924925 */ Lp4 = 2.2222198546e-01, /* 3E638E29 */ Lp5 = 1.8183572590e-01, /* 3E3A3325 */ Lp6 = 1.5313838422e-01, /* 3E1CD04F */ Lp7 = 1.4798198640e-01; /* 3E178897 */ static const float zero = 0.0; static volatile float vzero = 0.0; float log1pf(float x) { float hfsq,f,c,s,z,R,u; int32_t k,hx,hu,ax; GET_FLOAT_WORD(hx,x); ax = hx&0x7fffffff; k = 1; if (hx < 0x3ed413d0) { /* 1+x < sqrt(2)+ */ if(ax>=0x3f800000) { /* x <= -1.0 */ if(x==(float)-1.0) return -two25/vzero; /* log1p(-1)=+inf */ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ } if(ax<0x38000000) { /* |x| < 2**-15 */ if(two25+x>zero /* raise inexact */ &&ax<0x33800000) /* |x| < 2**-24 */ return x; else return x - x*x*(float)0.5; } if(hx>0||hx<=((int32_t)0xbe95f619)) { k=0;f=x;hu=1;} /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ } if (hx >= 0x7f800000) return x+x; if(k!=0) { if(hx<0x5a000000) { STRICT_ASSIGN(float,u,(float)1.0+x); GET_FLOAT_WORD(hu,u); k = (hu>>23)-127; /* correction term */ c = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0); c /= u; } else { u = x; GET_FLOAT_WORD(hu,u); k = (hu>>23)-127; c = 0; } hu &= 0x007fffff; /* * The approximation to sqrt(2) used in thresholds is not * critical. However, the ones used above must give less * strict bounds than the one here so that the k==0 case is * never reached from here, since here we have committed to * using the correction term but don't use it if k==0. */ if(hu<0x3504f4) { /* u < sqrt(2) */ SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */ } else { k += 1; SET_FLOAT_WORD(u,hu|0x3f000000); /* normalize u/2 */ hu = (0x00800000-hu)>>2; } f = u-(float)1.0; } hfsq=(float)0.5*f*f; if(hu==0) { /* |f| < 2**-20 */ if(f==zero) { if(k==0) { return zero; } else { c += k*ln2_lo; return k*ln2_hi+c; } } R = hfsq*((float)1.0-(float)0.66666666666666666*f); if(k==0) return f-R; else return k*ln2_hi-((R-(k*ln2_lo+c))-f); } s = f/((float)2.0+f); z = s*s; R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); if(k==0) return f-(hfsq-s*(hfsq+R)); else return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); } diff --git a/lib/msun/src/s_logb.c b/lib/msun/src/s_logb.c index b5ffff4fd11a..5ecdc2182523 100644 --- a/lib/msun/src/s_logb.c +++ b/lib/msun/src/s_logb.c @@ -1,47 +1,46 @@ /* @(#)s_logb.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * double logb(x) * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. * Use ilogb instead. */ #include #include "math.h" #include "math_private.h" static const double two54 = 1.80143985094819840000e+16; /* 43500000 00000000 */ double logb(double x) { int32_t lx,ix; EXTRACT_WORDS(ix,lx,x); ix &= 0x7fffffff; /* high |x| */ if((ix|lx)==0) return -1.0/fabs(x); if(ix>=0x7ff00000) return x*x; if(ix<0x00100000) { x *= two54; /* convert subnormal x to normal */ GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; return (double) ((ix>>20)-1023-54); } else return (double) ((ix>>20)-1023); } #if (LDBL_MANT_DIG == 53) __weak_reference(logb, logbl); #endif diff --git a/lib/msun/src/s_logbf.c b/lib/msun/src/s_logbf.c index 658c7d3a15c3..0416a9c4d101 100644 --- a/lib/msun/src/s_logbf.c +++ b/lib/msun/src/s_logbf.c @@ -1,38 +1,37 @@ /* s_logbf.c -- float version of s_logb.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float two25 = 3.355443200e+07; /* 0x4c000000 */ float logbf(float x) { int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* high |x| */ if(ix==0) return (float)-1.0/fabsf(x); if(ix>=0x7f800000) return x*x; if(ix<0x00800000) { x *= two25; /* convert subnormal x to normal */ GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; return (float) ((ix>>23)-127-25); } else return (float) ((ix>>23)-127); } diff --git a/lib/msun/src/s_logbl.c b/lib/msun/src/s_logbl.c index 280c302ac014..7466270e8ba2 100644 --- a/lib/msun/src/s_logbl.c +++ b/lib/msun/src/s_logbl.c @@ -1,52 +1,51 @@ /* * From: @(#)s_ilogb.c 5.1 93/09/24 * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include #include #include "fpmath.h" long double logbl(long double x) { union IEEEl2bits u; unsigned long m; int b; u.e = x; if (u.bits.exp == 0) { if ((u.bits.manl | u.bits.manh) == 0) { /* x == 0 */ u.bits.sign = 1; return (1.0L / u.e); } /* denormalized */ if (u.bits.manh == 0) { m = 1lu << (LDBL_MANL_SIZE - 1); for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1) b++; } else { m = 1lu << (LDBL_MANH_SIZE - 1); for (b = 0; !(u.bits.manh & m); m >>= 1) b++; } #ifdef LDBL_IMPLICIT_NBIT b++; #endif return ((long double)(LDBL_MIN_EXP - b - 1)); } if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1) /* normal */ return ((long double)(u.bits.exp - LDBL_MAX_EXP + 1)); else /* +/- inf or nan */ return (x * x); } diff --git a/lib/msun/src/s_lrint.c b/lib/msun/src/s_lrint.c index f4e56ac34b69..b1e96546db52 100644 --- a/lib/msun/src/s_lrint.c +++ b/lib/msun/src/s_lrint.c @@ -1,59 +1,58 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #ifndef type #define type double #define roundit rint #define dtype long #define fn lrint #endif /* * C99 says we should not raise a spurious inexact exception when an * invalid exception is raised. Unfortunately, the set of inputs * that overflows depends on the rounding mode when 'dtype' has more * significant bits than 'type'. Hence, we bend over backwards for the * sake of correctness; an MD implementation could be more efficient. */ dtype fn(type x) { fenv_t env; dtype d; feholdexcept(&env); d = (dtype)roundit(x); if (fetestexcept(FE_INVALID)) feclearexcept(FE_INEXACT); feupdateenv(&env); return (d); } diff --git a/lib/msun/src/s_lrintf.c b/lib/msun/src/s_lrintf.c index ca7cb99a3cf2..1c040e8d882b 100644 --- a/lib/msun/src/s_lrintf.c +++ b/lib/msun/src/s_lrintf.c @@ -1,7 +1,6 @@ -#include #define type float #define roundit rintf #define dtype long #define fn lrintf #include "s_lrint.c" diff --git a/lib/msun/src/s_lrintl.c b/lib/msun/src/s_lrintl.c index 7eedbc707c6e..91614e8ad264 100644 --- a/lib/msun/src/s_lrintl.c +++ b/lib/msun/src/s_lrintl.c @@ -1,7 +1,6 @@ -#include #define type long double #define roundit rintl #define dtype long #define fn lrintl #include "s_lrint.c" diff --git a/lib/msun/src/s_lround.c b/lib/msun/src/s_lround.c index 0b305918adc3..ae2f5ce7136a 100644 --- a/lib/msun/src/s_lround.c +++ b/lib/msun/src/s_lround.c @@ -1,69 +1,68 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #ifndef type #define type double #define roundit round #define dtype long #define DTYPE_MIN LONG_MIN #define DTYPE_MAX LONG_MAX #define fn lround #endif /* * If type has more precision than dtype, the endpoints dtype_(min|max) are * of the form xxx.5; they are "out of range" because lround() rounds away * from 0. On the other hand, if type has less precision than dtype, then * all values that are out of range are integral, so we might as well assume * that everything is in range. At compile time, INRANGE(x) should reduce to * two floating-point comparisons in the former case, or TRUE otherwise. */ static const type type_min = (type)DTYPE_MIN; static const type type_max = (type)DTYPE_MAX; static const type dtype_min = (type)DTYPE_MIN - 0.5; static const type dtype_max = (type)DTYPE_MAX + 0.5; #define INRANGE(x) (dtype_max - type_max != 0.5 || \ ((x) > dtype_min && (x) < dtype_max)) dtype fn(type x) { if (INRANGE(x)) { x = roundit(x); return ((dtype)x); } else { feraiseexcept(FE_INVALID); return (DTYPE_MAX); } } diff --git a/lib/msun/src/s_lroundf.c b/lib/msun/src/s_lroundf.c index e27e6a2fe187..86e63cc1d05c 100644 --- a/lib/msun/src/s_lroundf.c +++ b/lib/msun/src/s_lroundf.c @@ -1,9 +1,8 @@ -#include #define type float #define roundit roundf #define dtype long #define DTYPE_MIN LONG_MIN #define DTYPE_MAX LONG_MAX #define fn lroundf #include "s_lround.c" diff --git a/lib/msun/src/s_lroundl.c b/lib/msun/src/s_lroundl.c index cfd43bc7fbf1..57a2e90fc48e 100644 --- a/lib/msun/src/s_lroundl.c +++ b/lib/msun/src/s_lroundl.c @@ -1,9 +1,8 @@ -#include #define type long double #define roundit roundl #define dtype long #define DTYPE_MIN LONG_MIN #define DTYPE_MAX LONG_MAX #define fn lroundl #include "s_lround.c" diff --git a/lib/msun/src/s_modff.c b/lib/msun/src/s_modff.c index 57f59117a878..39f6c1c9f917 100644 --- a/lib/msun/src/s_modff.c +++ b/lib/msun/src/s_modff.c @@ -1,55 +1,54 @@ /* s_modff.c -- float version of s_modf.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float one = 1.0; float modff(float x, float *iptr) { int32_t i0,j0; u_int32_t i; GET_FLOAT_WORD(i0,x); j0 = ((i0>>23)&0xff)-0x7f; /* exponent of x */ if(j0<23) { /* integer part in x */ if(j0<0) { /* |x|<1 */ SET_FLOAT_WORD(*iptr,i0&0x80000000); /* *iptr = +-0 */ return x; } else { i = (0x007fffff)>>j0; if((i0&i)==0) { /* x is integral */ u_int32_t ix; *iptr = x; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ return x; } else { SET_FLOAT_WORD(*iptr,i0&(~i)); return x - *iptr; } } } else { /* no fraction part */ u_int32_t ix; *iptr = x*one; if (x != x) /* NaN */ return x; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ return x; } } diff --git a/lib/msun/src/s_nearbyint.c b/lib/msun/src/s_nearbyint.c index 96604594c499..3dcaf98b369a 100644 --- a/lib/msun/src/s_nearbyint.c +++ b/lib/msun/src/s_nearbyint.c @@ -1,59 +1,58 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include /* * We save and restore the floating-point environment to avoid raising * an inexact exception. We can get away with using fesetenv() * instead of feclearexcept()/feupdateenv() to restore the environment * because the only exception defined for rint() is overflow, and * rounding can't overflow as long as emax >= p. * * The volatile keyword is needed below because clang incorrectly assumes * that rint won't raise any floating-point exceptions. Declaring ret volatile * is sufficient to trick the compiler into doing the right thing. */ #define DECL(type, fn, rint) \ type \ fn(type x) \ { \ volatile type ret; \ fenv_t env; \ \ fegetenv(&env); \ ret = rint(x); \ fesetenv(&env); \ return (ret); \ } DECL(double, nearbyint, rint) DECL(float, nearbyintf, rintf) DECL(long double, nearbyintl, rintl) diff --git a/lib/msun/src/s_nextafter.c b/lib/msun/src/s_nextafter.c index 99c65b11aeba..8316ba41d78c 100644 --- a/lib/msun/src/s_nextafter.c +++ b/lib/msun/src/s_nextafter.c @@ -1,81 +1,80 @@ /* @(#)s_nextafter.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* IEEE functions * nextafter(x,y) * return the next machine floating-point number of x in the * direction toward y. * Special cases: */ #include #include "math.h" #include "math_private.h" double nextafter(double x, double y) { volatile double t; int32_t hx,hy,ix,iy; u_int32_t lx,ly; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */ t = x*x; if(t==x) return t; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } hy = hx&0x7ff00000; if(hy>=0x7ff00000) return x+x; /* overflow */ if(hy<0x00100000) { /* underflow */ t = x*x; if(t!=x) { /* raise underflow flag */ INSERT_WORDS(y,hx,lx); return y; } } INSERT_WORDS(x,hx,lx); return x; } #if (LDBL_MANT_DIG == 53) __weak_reference(nextafter, nexttoward); __weak_reference(nextafter, nexttowardl); __weak_reference(nextafter, nextafterl); #endif diff --git a/lib/msun/src/s_nextafterf.c b/lib/msun/src/s_nextafterf.c index 18e046324957..418b126a27ab 100644 --- a/lib/msun/src/s_nextafterf.c +++ b/lib/msun/src/s_nextafterf.c @@ -1,64 +1,63 @@ /* s_nextafterf.c -- float version of s_nextafter.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" float nextafterf(float x, float y) { volatile float t; int32_t hx,hy,ix,iy; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>0x7f800000)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */ t = x*x; if(t==x) return t; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if(hx>hy) { /* x > y, x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy){ /* x < y, x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) return x+x; /* overflow */ if(hy<0x00800000) { /* underflow */ t = x*x; if(t!=x) { /* raise underflow flag */ SET_FLOAT_WORD(y,hx); return y; } } SET_FLOAT_WORD(x,hx); return x; } diff --git a/lib/msun/src/s_nextafterl.c b/lib/msun/src/s_nextafterl.c index 168dbb4ed093..7df6c008910d 100644 --- a/lib/msun/src/s_nextafterl.c +++ b/lib/msun/src/s_nextafterl.c @@ -1,78 +1,77 @@ /* @(#)s_nextafter.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* IEEE functions * nextafter(x,y) * return the next machine floating-point number of x in the * direction toward y. * Special cases: */ #include #include "fpmath.h" #include "math.h" #include "math_private.h" #if LDBL_MAX_EXP != 0x4000 #error "Unsupported long double format" #endif long double nextafterl(long double x, long double y) { volatile long double t; union IEEEl2bits ux, uy; ux.e = x; uy.e = y; if ((ux.bits.exp == 0x7fff && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) || (uy.bits.exp == 0x7fff && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) return x+y; /* x or y is nan */ if(x==y) return y; /* x=y, return y */ if(x==0.0) { ux.bits.manh = 0; /* return +-minsubnormal */ ux.bits.manl = 1; ux.bits.sign = uy.bits.sign; t = ux.e*ux.e; if(t==ux.e) return t; else return ux.e; /* raise underflow flag */ } if(x>0.0 ^ x /* * We assume that a long double has a 15-bit exponent. On systems * where long double is the same as double, nexttoward() is an alias * for nextafter(), so we don't use this routine. */ #include #include "fpmath.h" #include "math.h" #include "math_private.h" #if LDBL_MAX_EXP != 0x4000 #error "Unsupported long double format" #endif double nexttoward(double x, long double y) { union IEEEl2bits uy; volatile double t; int32_t hx,ix; u_int32_t lx; EXTRACT_WORDS(hx,lx,x); ix = hx&0x7fffffff; /* |x| */ uy.e = y; if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || (uy.bits.exp == 0x7fff && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) return x+y; /* x or y is nan */ if(x==y) return (double)y; /* x=y, return y */ if(x==0.0) { INSERT_WORDS(x,uy.bits.sign<<31,1); /* return +-minsubnormal */ t = x*x; if(t==x) return t; else return x; /* raise underflow flag */ } if(hx>0.0 ^ x < y) { /* x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x += ulp */ lx += 1; if(lx==0) hx += 1; } ix = hx&0x7ff00000; if(ix>=0x7ff00000) return x+x; /* overflow */ if(ix<0x00100000) { /* underflow */ t = x*x; if(t!=x) { /* raise underflow flag */ INSERT_WORDS(x,hx,lx); return x; } } INSERT_WORDS(x,hx,lx); return x; } diff --git a/lib/msun/src/s_nexttowardf.c b/lib/msun/src/s_nexttowardf.c index 03d8cc5e4729..05c89f4554ec 100644 --- a/lib/msun/src/s_nexttowardf.c +++ b/lib/msun/src/s_nexttowardf.c @@ -1,57 +1,56 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define LDBL_INFNAN_EXP (LDBL_MAX_EXP * 2 - 1) float nexttowardf(float x, long double y) { union IEEEl2bits uy; volatile float t; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; /* |x| */ uy.e = y; if((ix>0x7f800000) || (uy.bits.exp == LDBL_INFNAN_EXP && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) return x+y; /* x or y is nan */ if(x==y) return (float)y; /* x=y, return y */ if(ix==0) { /* x == 0 */ SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */ t = x*x; if(t==x) return t; else return x; /* raise underflow flag */ } if(hx>=0 ^ x < y) /* x -= ulp */ hx -= 1; else /* x += ulp */ hx += 1; ix = hx&0x7f800000; if(ix>=0x7f800000) return x+x; /* overflow */ if(ix<0x00800000) { /* underflow */ t = x*x; if(t!=x) { /* raise underflow flag */ SET_FLOAT_WORD(x,hx); return x; } } SET_FLOAT_WORD(x,hx); return x; } diff --git a/lib/msun/src/s_remquo.c b/lib/msun/src/s_remquo.c index e3aac25230e0..a3f73f779c1b 100644 --- a/lib/msun/src/s_remquo.c +++ b/lib/msun/src/s_remquo.c @@ -1,157 +1,156 @@ /* @(#)e_fmod.c 1.3 95/01/18 */ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #include "math_private.h" static const double Zero[] = {0.0, -0.0,}; /* * Return the IEEE remainder and set *quo to the last n bits of the * quotient, rounded to the nearest integer. We choose n=31 because * we wind up computing all the integer bits of the quotient anyway as * a side-effect of computing the remainder by the shift and subtract * method. In practice, this is far more bits than are needed to use * remquo in reduction algorithms. */ double remquo(double x, double y, int *quo) { int32_t n,hx,hy,hz,ix,iy,sx,i; u_int32_t lx,ly,lz,q,sxy; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hy,ly,y); sxy = (hx ^ hy) & 0x80000000; sx = hx&0x80000000; /* sign of x */ hx ^=sx; /* |x| */ hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(hx<=hy) { if((hx>31]; /* |x|=|y| return x*0*/ } } /* determine ix = ilogb(x) */ if(hx<0x00100000) { /* subnormal x */ if(hx==0) { for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; } else { for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; } } else ix = (hx>>20)-1023; /* determine iy = ilogb(y) */ if(hy<0x00100000) { /* subnormal y */ if(hy==0) { for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; } else { for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; } } else iy = (hy>>20)-1023; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -1022) hx = 0x00100000|(0x000fffff&hx); else { /* subnormal x, shift x to normal */ n = -1022-ix; if(n<=31) { hx = (hx<>(32-n)); lx <<= n; } else { hx = lx<<(n-32); lx = 0; } } if(iy >= -1022) hy = 0x00100000|(0x000fffff&hy); else { /* subnormal y, shift y to normal */ n = -1022-iy; if(n<=31) { hy = (hy<>(32-n)); ly <<= n; } else { hy = ly<<(n-32); ly = 0; } } /* fix point fmod */ n = ix - iy; q = 0; while(n--) { hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} else {hx = hz+hz+(lz>>31); lx = lz+lz; q++;} q <<= 1; } hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;q++;} /* convert back to floating value and restore the sign */ if((hx|lx)==0) { /* return sign(x)*0 */ q &= 0x7fffffff; *quo = (sxy ? -q : q); return Zero[(u_int32_t)sx>>31]; } while(hx<0x00100000) { /* normalize x */ hx = hx+hx+(lx>>31); lx = lx+lx; iy -= 1; } if(iy>= -1022) { /* normalize output */ hx = ((hx-0x00100000)|((iy+1023)<<20)); } else { /* subnormal output */ n = -1022 - iy; if(n<=20) { lx = (lx>>n)|((u_int32_t)hx<<(32-n)); hx >>= n; } else if (n<=31) { lx = (hx<<(32-n))|(lx>>n); hx = 0; } else { lx = hx>>(n-32); hx = 0; } } fixup: INSERT_WORDS(x,hx,lx); y = fabs(y); if (y < 0x1p-1021) { if (x+x>y || (x+x==y && (q & 1))) { q++; x-=y; } } else if (x>0.5*y || (x==0.5*y && (q & 1))) { q++; x-=y; } GET_HIGH_WORD(hx,x); SET_HIGH_WORD(x,hx^sx); q &= 0x7fffffff; *quo = (sxy ? -q : q); return x; } #if LDBL_MANT_DIG == 53 __weak_reference(remquo, remquol); #endif diff --git a/lib/msun/src/s_remquof.c b/lib/msun/src/s_remquof.c index c42bd8c4320d..5818cc55cf6f 100644 --- a/lib/msun/src/s_remquof.c +++ b/lib/msun/src/s_remquof.c @@ -1,120 +1,119 @@ /* @(#)e_fmod.c 1.3 95/01/18 */ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const float Zero[] = {0.0, -0.0,}; /* * Return the IEEE remainder and set *quo to the last n bits of the * quotient, rounded to the nearest integer. We choose n=31 because * we wind up computing all the integer bits of the quotient anyway as * a side-effect of computing the remainder by the shift and subtract * method. In practice, this is far more bits than are needed to use * remquo in reduction algorithms. */ float remquof(float x, float y, int *quo) { int32_t n,hx,hy,hz,ix,iy,sx,i; u_int32_t q,sxy; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); sxy = (hx ^ hy) & 0x80000000; sx = hx&0x80000000; /* sign of x */ hx ^=sx; /* |x| */ hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if(hy==0||hx>=0x7f800000||hy>0x7f800000) /* y=0,NaN;or x not finite */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(hx>31]; /* |x|=|y| return x*0*/ } /* determine ix = ilogb(x) */ if(hx<0x00800000) { /* subnormal x */ for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; } else ix = (hx>>23)-127; /* determine iy = ilogb(y) */ if(hy<0x00800000) { /* subnormal y */ for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1; } else iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) hx = 0x00800000|(0x007fffff&hx); else { /* subnormal x, shift x to normal */ n = -126-ix; hx <<= n; } if(iy >= -126) hy = 0x00800000|(0x007fffff&hy); else { /* subnormal y, shift y to normal */ n = -126-iy; hy <<= n; } /* fix point fmod */ n = ix - iy; q = 0; while(n--) { hz=hx-hy; if(hz<0) hx = hx << 1; else {hx = hz << 1; q++;} q <<= 1; } hz=hx-hy; if(hz>=0) {hx=hz;q++;} /* convert back to floating value and restore the sign */ if(hx==0) { /* return sign(x)*0 */ q &= 0x7fffffff; *quo = (sxy ? -q : q); return Zero[(u_int32_t)sx>>31]; } while(hx<0x00800000) { /* normalize x */ hx <<= 1; iy -= 1; } if(iy>= -126) { /* normalize output */ hx = ((hx-0x00800000)|((iy+127)<<23)); } else { /* subnormal output */ n = -126 - iy; hx >>= n; } fixup: SET_FLOAT_WORD(x,hx); y = fabsf(y); if (y < 0x1p-125f) { if (x+x>y || (x+x==y && (q & 1))) { q++; x-=y; } } else if (x>0.5f*y || (x==0.5f*y && (q & 1))) { q++; x-=y; } GET_FLOAT_WORD(hx,x); SET_FLOAT_WORD(x,hx^sx); q &= 0x7fffffff; *quo = (sxy ? -q : q); return x; } diff --git a/lib/msun/src/s_remquol.c b/lib/msun/src/s_remquol.c index a0f93d4fcae0..b0a99fc84d49 100644 --- a/lib/msun/src/s_remquol.c +++ b/lib/msun/src/s_remquol.c @@ -1,171 +1,170 @@ /* @(#)e_fmod.c 1.3 95/01/18 */ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include #include "fpmath.h" #include "math.h" #include "math_private.h" #define BIAS (LDBL_MAX_EXP - 1) #if LDBL_MANL_SIZE > 32 typedef uint64_t manl_t; #else typedef uint32_t manl_t; #endif #if LDBL_MANH_SIZE > 32 typedef uint64_t manh_t; #else typedef uint32_t manh_t; #endif /* * These macros add and remove an explicit integer bit in front of the * fractional mantissa, if the architecture doesn't have such a bit by * default already. */ #ifdef LDBL_IMPLICIT_NBIT #define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE)) #define HFRAC_BITS LDBL_MANH_SIZE #else #define SET_NBIT(hx) (hx) #define HFRAC_BITS (LDBL_MANH_SIZE - 1) #endif #define MANL_SHIFT (LDBL_MANL_SIZE - 1) static const long double Zero[] = {0.0L, -0.0L}; /* * Return the IEEE remainder and set *quo to the last n bits of the * quotient, rounded to the nearest integer. We choose n=31 because * we wind up computing all the integer bits of the quotient anyway as * a side-effect of computing the remainder by the shift and subtract * method. In practice, this is far more bits than are needed to use * remquo in reduction algorithms. * * Assumptions: * - The low part of the mantissa fits in a manl_t exactly. * - The high part of the mantissa fits in an int64_t with enough room * for an explicit integer bit in front of the fractional bits. */ long double remquol(long double x, long double y, int *quo) { union IEEEl2bits ux, uy; int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */ manh_t hy; manl_t lx,ly,lz; int ix,iy,n,q,sx,sxy; ux.e = x; uy.e = y; sx = ux.bits.sign; sxy = sx ^ uy.bits.sign; ux.bits.sign = 0; /* |x| */ uy.bits.sign = 0; /* |y| */ /* purge off exception values */ if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */ (ux.bits.exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */ (uy.bits.exp == BIAS + LDBL_MAX_EXP && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */ return nan_mix_op(x, y, *)/nan_mix_op(x, y, *); if(ux.bits.exp<=uy.bits.exp) { if((ux.bits.exp>MANL_SHIFT); lx = lx+lx;} else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;} q <<= 1; } hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;q++;} /* convert back to floating value and restore the sign */ if((hx|lx)==0) { /* return sign(x)*0 */ q &= 0x7fffffff; *quo = (sxy ? -q : q); return Zero[sx]; } while(hx<(1ULL<>MANL_SHIFT); lx = lx+lx; iy -= 1; } ux.bits.manh = hx; /* The integer bit is truncated here if needed. */ ux.bits.manl = lx; if (iy < LDBL_MIN_EXP) { ux.bits.exp = iy + (BIAS + 512); ux.e *= 0x1p-512; } else { ux.bits.exp = iy + BIAS; } fixup: x = ux.e; /* |x| */ y = fabsl(y); if (y < LDBL_MIN * 2) { if (x+x>y || (x+x==y && (q & 1))) { q++; x-=y; } } else if (x>0.5*y || (x==0.5*y && (q & 1))) { q++; x-=y; } ux.e = x; ux.bits.sign ^= sx; x = ux.e; q &= 0x7fffffff; *quo = (sxy ? -q : q); return x; } diff --git a/lib/msun/src/s_rint.c b/lib/msun/src/s_rint.c index 96faf6a007ee..9ba10f69fcc5 100644 --- a/lib/msun/src/s_rint.c +++ b/lib/msun/src/s_rint.c @@ -1,90 +1,89 @@ /* @(#)s_rint.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * rint(x) * Return x rounded to integral value according to the prevailing * rounding mode. * Method: * Using floating addition. * Exception: * Inexact flag raised if x not equal to rint(x). */ #include #include "math.h" #include "math_private.h" static const double TWO52[2]={ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ }; double rint(double x) { int32_t i0,j0,sx; u_int32_t i,i1; double w,t; EXTRACT_WORDS(i0,i1,x); sx = (i0>>31)&1; j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { if(((i0&0x7fffffff)|i1)==0) return x; i1 |= (i0&0x0fffff); i0 &= 0xfffe0000; i0 |= ((i1|-i1)>>12)&0x80000; SET_HIGH_WORD(x,i0); STRICT_ASSIGN(double,w,TWO52[sx]+x); t = w-TWO52[sx]; GET_HIGH_WORD(i0,t); SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); return t; } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ i>>=1; if(((i0&i)|i1)!=0) { /* * Some bit is set after the 0.5 bit. To avoid the * possibility of errors from double rounding in * w = TWO52[sx]+x, adjust the 0.25 bit to a lower * guard bit. We do this for all j0<=51. The * adjustment is trickiest for j0==18 and j0==19 * since then it spans the word boundary. */ if(j0==19) i1 = 0x40000000; else if(j0==18) i1 = 0x80000000; else i0 = (i0&(~i))|((0x20000)>>j0); } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((u_int32_t)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ i>>=1; if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); } INSERT_WORDS(x,i0,i1); STRICT_ASSIGN(double,w,TWO52[sx]+x); return w-TWO52[sx]; } #if (LDBL_MANT_DIG == 53) __weak_reference(rint, rintl); #endif diff --git a/lib/msun/src/s_rintf.c b/lib/msun/src/s_rintf.c index 328738f0ba0c..3f0cb906ae85 100644 --- a/lib/msun/src/s_rintf.c +++ b/lib/msun/src/s_rintf.c @@ -1,51 +1,50 @@ /* s_rintf.c -- float version of s_rint.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include #include "math.h" #include "math_private.h" static const float TWO23[2]={ 8.3886080000e+06, /* 0x4b000000 */ -8.3886080000e+06, /* 0xcb000000 */ }; float rintf(float x) { int32_t i0,j0,sx; float w,t; GET_FLOAT_WORD(i0,x); sx = (i0>>31)&1; j0 = ((i0>>23)&0xff)-0x7f; if(j0<23) { if(j0<0) { if((i0&0x7fffffff)==0) return x; STRICT_ASSIGN(float,w,TWO23[sx]+x); t = w-TWO23[sx]; GET_FLOAT_WORD(i0,t); SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); return t; } STRICT_ASSIGN(float,w,TWO23[sx]+x); return w-TWO23[sx]; } if(j0==0x80) return x+x; /* inf or NaN */ else return x; /* x is integral */ } diff --git a/lib/msun/src/s_rintl.c b/lib/msun/src/s_rintl.c index 15bce02e219d..72c9cabd1a91 100644 --- a/lib/msun/src/s_rintl.c +++ b/lib/msun/src/s_rintl.c @@ -1,90 +1,89 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include "fpmath.h" #if LDBL_MAX_EXP != 0x4000 /* We also require the usual bias, min exp and expsign packing. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const float shift[2] = { #if LDBL_MANT_DIG == 64 0x1.0p63, -0x1.0p63 #elif LDBL_MANT_DIG == 113 0x1.0p112, -0x1.0p112 #else #error "Unsupported long double format" #endif }; static const float zero[2] = { 0.0, -0.0 }; long double rintl(long double x) { union IEEEl2bits u; uint32_t expsign; int ex, sign; u.e = x; expsign = u.xbits.expsign; ex = expsign & 0x7fff; if (ex >= BIAS + LDBL_MANT_DIG - 1) { if (ex == BIAS + LDBL_MAX_EXP) return (x + x); /* Inf, NaN, or unsupported format */ return (x); /* finite and already an integer */ } sign = expsign >> 15; /* * The following code assumes that intermediate results are * evaluated in long double precision. If they are evaluated in * greater precision, double rounding may occur, and if they are * evaluated in less precision (as on i386), results will be * wildly incorrect. */ x += shift[sign]; x -= shift[sign]; /* * If the result is +-0, then it must have the same sign as x, but * the above calculation doesn't always give this. Fix up the sign. */ if (ex < BIAS && x == 0.0L) return (zero[sign]); return (x); } diff --git a/lib/msun/src/s_round.c b/lib/msun/src/s_round.c index 04d49c220973..c1b55f58765e 100644 --- a/lib/msun/src/s_round.c +++ b/lib/msun/src/s_round.c @@ -1,60 +1,59 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2003, Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include "math.h" #include "math_private.h" double round(double x) { double t; uint32_t hx; GET_HIGH_WORD(hx, x); if ((hx & 0x7fffffff) == 0x7ff00000) return (x + x); if (!(hx & 0x80000000)) { t = floor(x); if (t - x <= -0.5) t += 1; return (t); } else { t = floor(-x); if (t + x <= -0.5) t += 1; return (-t); } } #if (LDBL_MANT_DIG == 53) __weak_reference(round, roundl); #endif diff --git a/lib/msun/src/s_roundf.c b/lib/msun/src/s_roundf.c index 795d88df3050..7c09e090ff9a 100644 --- a/lib/msun/src/s_roundf.c +++ b/lib/msun/src/s_roundf.c @@ -1,54 +1,53 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2003, Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include "math.h" #include "math_private.h" float roundf(float x) { float t; uint32_t hx; GET_FLOAT_WORD(hx, x); if ((hx & 0x7fffffff) == 0x7f800000) return (x + x); if (!(hx & 0x80000000)) { t = floorf(x); if (t - x <= -0.5F) t += 1; return (t); } else { t = floorf(-x); if (t + x <= -0.5F) t += 1; return (-t); } } diff --git a/lib/msun/src/s_roundl.c b/lib/msun/src/s_roundl.c index 05cb3e9f4918..bc5dfe550165 100644 --- a/lib/msun/src/s_roundl.c +++ b/lib/msun/src/s_roundl.c @@ -1,62 +1,61 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2003, Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #ifdef __i386__ #include #endif #include "fpmath.h" #include "math.h" #include "math_private.h" long double roundl(long double x) { long double t; uint16_t hx; GET_LDBL_EXPSIGN(hx, x); if ((hx & 0x7fff) == 0x7fff) return (x + x); ENTERI(); if (!(hx & 0x8000)) { t = floorl(x); if (t - x <= -0.5L) t += 1; RETURNI(t); } else { t = floorl(-x); if (t + x <= -0.5L) t += 1; RETURNI(-t); } } diff --git a/lib/msun/src/s_scalbln.c b/lib/msun/src/s_scalbln.c index ff402b0f8fab..42e4669b3986 100644 --- a/lib/msun/src/s_scalbln.c +++ b/lib/msun/src/s_scalbln.c @@ -1,54 +1,53 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #define NMAX 65536 #define NMIN -65536 double scalbln(double x, long n) { return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); } float scalblnf(float x, long n) { return (scalbnf(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); } long double scalblnl(long double x, long n) { return (scalbnl(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); } diff --git a/lib/msun/src/s_significand.c b/lib/msun/src/s_significand.c index 29ff0cc29807..7bbe6d1a457e 100644 --- a/lib/msun/src/s_significand.c +++ b/lib/msun/src/s_significand.c @@ -1,27 +1,26 @@ /* @(#)s_signif.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * significand(x) computes just * scalb(x, (double) -ilogb(x)), * for exercising the fraction-part(F) IEEE 754-1985 test vector. */ #include "math.h" #include "math_private.h" double significand(double x) { return scalb(x,(double) -ilogb(x)); } diff --git a/lib/msun/src/s_significandf.c b/lib/msun/src/s_significandf.c index 9fd919d65a91..3cdaa4daa753 100644 --- a/lib/msun/src/s_significandf.c +++ b/lib/msun/src/s_significandf.c @@ -1,24 +1,23 @@ /* s_significandf.c -- float version of s_significand.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" float significandf(float x) { return scalbf(x,(float) -ilogbf(x)); } diff --git a/lib/msun/src/s_sin.c b/lib/msun/src/s_sin.c index e9cd928d300b..32fd08184cd8 100644 --- a/lib/msun/src/s_sin.c +++ b/lib/msun/src/s_sin.c @@ -1,87 +1,86 @@ /* @(#)s_sin.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* sin(x) * Return sine function of x. * * kernel function: * __kernel_sin ... sine function on [-pi/4,pi/4] * __kernel_cos ... cose function on [-pi/4,pi/4] * __ieee754_rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include #include "math.h" #define INLINE_REM_PIO2 #include "math_private.h" #include "e_rem_pio2.c" double sin(double x) { double y[2],z=0.0; int32_t n, ix; /* High word of x. */ GET_HIGH_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) { if(ix<0x3e500000) /* |x| < 2**-26 */ {if((int)x==0) return x;} /* generate inexact */ return __kernel_sin(x,z,0); } /* sin(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); switch(n&3) { case 0: return __kernel_sin(y[0],y[1],1); case 1: return __kernel_cos(y[0],y[1]); case 2: return -__kernel_sin(y[0],y[1],1); default: return -__kernel_cos(y[0],y[1]); } } } #if (LDBL_MANT_DIG == 53) __weak_reference(sin, sinl); #endif diff --git a/lib/msun/src/s_sincos.c b/lib/msun/src/s_sincos.c index 028ce416280a..4e819ea89128 100644 --- a/lib/msun/src/s_sincos.c +++ b/lib/msun/src/s_sincos.c @@ -1,78 +1,77 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * s_sin.c and s_cos.c merged by Steven G. Kargl. Descriptions of the * algorithms are contained in the original files. */ -#include #include #include "math.h" #define INLINE_REM_PIO2 #include "math_private.h" #include "e_rem_pio2.c" #include "k_sincos.h" void sincos(double x, double *sn, double *cs) { double y[2]; int32_t n, ix; /* High word of x. */ GET_HIGH_WORD(ix, x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if (ix <= 0x3fe921fb) { if (ix < 0x3e400000) { /* |x| < 2**-27 */ if ((int)x == 0) { /* Generate inexact. */ *sn = x; *cs = 1; return; } } __kernel_sincos(x, 0, 0, sn, cs); return; } /* If x = Inf or NaN, then sin(x) = NaN and cos(x) = NaN. */ if (ix >= 0x7ff00000) { *sn = x - x; *cs = x - x; return; } /* Argument reduction. */ n = __ieee754_rem_pio2(x, y); switch(n & 3) { case 0: __kernel_sincos(y[0], y[1], 1, sn, cs); break; case 1: __kernel_sincos(y[0], y[1], 1, cs, sn); *cs = -*cs; break; case 2: __kernel_sincos(y[0], y[1], 1, sn, cs); *sn = -*sn; *cs = -*cs; break; default: __kernel_sincos(y[0], y[1], 1, cs, sn); *sn = -*sn; } } #if (LDBL_MANT_DIG == 53) __weak_reference(sincos, sincosl); #endif diff --git a/lib/msun/src/s_sincosf.c b/lib/msun/src/s_sincosf.c index ee9f03444944..eaf7be84ee35 100644 --- a/lib/msun/src/s_sincosf.c +++ b/lib/msun/src/s_sincosf.c @@ -1,124 +1,123 @@ /*- * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* s_sincosf.c -- float version of s_sincos.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. * Merged s_sinf.c and s_cosf.c by Steven G. Kargl. */ -#include #include #include "math.h" #define INLINE_REM_PIO2F #include "math_private.h" #include "e_rem_pio2f.c" #include "k_sincosf.h" /* Small multiples of pi/2 rounded to double precision. */ static const double p1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ p2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ p3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ p4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ void sincosf(float x, float *sn, float *cs) { float c, s; double y; int32_t n, hx, ix; GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ if (ix < 0x39800000) { /* |x| < 2**-12 */ if ((int)x == 0) { *sn = x; /* x with inexact if x != 0 */ *cs = 1; return; } } __kernel_sincosdf(x, sn, cs); return; } if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */ if (ix <= 0x4016cbe3) { /* |x| ~<= 3pi/4 */ if (hx > 0) { __kernel_sincosdf(x - p1pio2, cs, sn); *cs = -*cs; } else { __kernel_sincosdf(x + p1pio2, cs, sn); *sn = -*sn; } } else { if (hx > 0) __kernel_sincosdf(x - p2pio2, sn, cs); else __kernel_sincosdf(x + p2pio2, sn, cs); *sn = -*sn; *cs = -*cs; } return; } if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */ if (ix <= 0x40afeddf) { /* |x| ~<= 7*pi/4 */ if (hx > 0) { __kernel_sincosdf(x - p3pio2, cs, sn); *sn = -*sn; } else { __kernel_sincosdf(x + p3pio2, cs, sn); *cs = -*cs; } } else { if (hx > 0) __kernel_sincosdf(x - p4pio2, sn, cs); else __kernel_sincosdf(x + p4pio2, sn, cs); } return; } /* If x = Inf or NaN, then sin(x) = NaN and cos(x) = NaN. */ if (ix >= 0x7f800000) { *sn = x - x; *cs = x - x; return; } /* Argument reduction. */ n = __ieee754_rem_pio2f(x, &y); __kernel_sincosdf(y, &s, &c); switch(n & 3) { case 0: *sn = s; *cs = c; break; case 1: *sn = c; *cs = -s; break; case 2: *sn = -s; *cs = -c; break; default: *sn = -c; *cs = s; } } diff --git a/lib/msun/src/s_sincosl.c b/lib/msun/src/s_sincosl.c index 2d3833c93d46..7fb69aa4d4dd 100644 --- a/lib/msun/src/s_sincosl.c +++ b/lib/msun/src/s_sincosl.c @@ -1,102 +1,101 @@ /*- * Copyright (c) 2007, 2010-2013 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * s_sinl.c and s_cosl.c merged by Steven G. Kargl. */ -#include #include #ifdef __i386__ #include #endif #include "math.h" #include "math_private.h" #include "k_sincosl.h" #if LDBL_MANT_DIG == 64 #include "../ld80/e_rem_pio2l.h" #elif LDBL_MANT_DIG == 113 #include "../ld128/e_rem_pio2l.h" #else #error "Unsupported long double format" #endif void sincosl(long double x, long double *sn, long double *cs) { union IEEEl2bits z; int e0; long double y[2]; z.e = x; z.bits.sign = 0; ENTERV(); /* Optimize the case where x is already within range. */ if (z.e < M_PI_4) { /* * If x = +-0 or x is a subnormal number, then sin(x) = x and * cos(x) = 1. */ if (z.bits.exp == 0) { *sn = x; *cs = 1; } else __kernel_sincosl(x, 0, 0, sn, cs); RETURNV(); } /* If x = NaN or Inf, then sin(x) and cos(x) are NaN. */ if (z.bits.exp == 32767) { *sn = x - x; *cs = x - x; RETURNV(); } /* Range reduction. */ e0 = __ieee754_rem_pio2l(x, y); switch (e0 & 3) { case 0: __kernel_sincosl(y[0], y[1], 1, sn, cs); break; case 1: __kernel_sincosl(y[0], y[1], 1, cs, sn); *cs = -*cs; break; case 2: __kernel_sincosl(y[0], y[1], 1, sn, cs); *sn = -*sn; *cs = -*cs; break; default: __kernel_sincosl(y[0], y[1], 1, cs, sn); *sn = -*sn; } RETURNV(); } diff --git a/lib/msun/src/s_sinf.c b/lib/msun/src/s_sinf.c index 9837e80bb6ff..85fb11540a7d 100644 --- a/lib/msun/src/s_sinf.c +++ b/lib/msun/src/s_sinf.c @@ -1,83 +1,82 @@ /* s_sinf.c -- float version of s_sin.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #define INLINE_KERNEL_COSDF #define INLINE_KERNEL_SINDF #define INLINE_REM_PIO2F #include "math_private.h" #include "e_rem_pio2f.c" #include "k_cosf.c" #include "k_sinf.c" /* Small multiples of pi/2 rounded to double precision. */ static const double s1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ s2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ s3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ s4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ float sinf(float x) { double y; int32_t n, hx, ix; GET_FLOAT_WORD(hx,x); ix = hx & 0x7fffffff; if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ if(ix<0x39800000) /* |x| < 2**-12 */ if(((int)x)==0) return x; /* x with inexact if x != 0 */ return __kernel_sindf(x); } if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */ if(ix<=0x4016cbe3) { /* |x| ~<= 3pi/4 */ if(hx>0) return __kernel_cosdf(x - s1pio2); else return -__kernel_cosdf(x + s1pio2); } else return __kernel_sindf((hx > 0 ? s2pio2 : -s2pio2) - x); } if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */ if(ix<=0x40afeddf) { /* |x| ~<= 7*pi/4 */ if(hx>0) return -__kernel_cosdf(x - s3pio2); else return __kernel_cosdf(x + s3pio2); } else return __kernel_sindf(x + (hx > 0 ? -s4pio2 : s4pio2)); } /* sin(Inf or NaN) is NaN */ else if (ix>=0x7f800000) return x-x; /* general argument reduction needed */ else { n = __ieee754_rem_pio2f(x,&y); switch(n&3) { case 0: return __kernel_sindf(y); case 1: return __kernel_cosdf(y); case 2: return __kernel_sindf(-y); default: return -__kernel_cosdf(y); } } } diff --git a/lib/msun/src/s_sinl.c b/lib/msun/src/s_sinl.c index 605a4b4b6272..d0b7b34718f8 100644 --- a/lib/msun/src/s_sinl.c +++ b/lib/msun/src/s_sinl.c @@ -1,93 +1,92 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #ifdef __i386__ #include #endif #include "math.h" #include "math_private.h" #if LDBL_MANT_DIG == 64 #include "../ld80/e_rem_pio2l.h" #elif LDBL_MANT_DIG == 113 #include "../ld128/e_rem_pio2l.h" #else #error "Unsupported long double format" #endif long double sinl(long double x) { union IEEEl2bits z; int e0, s; long double y[2]; long double hi, lo; z.e = x; s = z.bits.sign; z.bits.sign = 0; /* If x = +-0 or x is a subnormal number, then sin(x) = x */ if (z.bits.exp == 0) return (x); /* If x = NaN or Inf, then sin(x) = NaN. */ if (z.bits.exp == 32767) return ((x - x) / (x - x)); ENTERI(); /* Optimize the case where x is already within range. */ if (z.e < M_PI_4) { hi = __kernel_sinl(z.e, 0, 0); RETURNI(s ? -hi : hi); } e0 = __ieee754_rem_pio2l(x, y); hi = y[0]; lo = y[1]; switch (e0 & 3) { case 0: hi = __kernel_sinl(hi, lo, 1); break; case 1: hi = __kernel_cosl(hi, lo); break; case 2: hi = - __kernel_sinl(hi, lo, 1); break; case 3: hi = - __kernel_cosl(hi, lo); break; } RETURNI(hi); } diff --git a/lib/msun/src/s_tan.c b/lib/msun/src/s_tan.c index be5154e89468..2a5959765aaa 100644 --- a/lib/msun/src/s_tan.c +++ b/lib/msun/src/s_tan.c @@ -1,81 +1,80 @@ /* @(#)s_tan.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* tan(x) * Return tangent function of x. * * kernel function: * __kernel_tan ... tangent function on [-pi/4,pi/4] * __ieee754_rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include #include "math.h" #define INLINE_REM_PIO2 #include "math_private.h" #include "e_rem_pio2.c" double tan(double x) { double y[2],z=0.0; int32_t n, ix; /* High word of x. */ GET_HIGH_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) { if(ix<0x3e400000) /* x < 2**-27 */ if((int)x==0) return x; /* generate inexact */ return __kernel_tan(x,z,1); } /* tan(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* NaN */ /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even -1 -- n odd */ } } #if (LDBL_MANT_DIG == 53) __weak_reference(tan, tanl); #endif diff --git a/lib/msun/src/s_tanf.c b/lib/msun/src/s_tanf.c index 1b72cd6cae91..2462f96ba45f 100644 --- a/lib/msun/src/s_tanf.c +++ b/lib/msun/src/s_tanf.c @@ -1,70 +1,69 @@ /* s_tanf.c -- float version of s_tan.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. * Optimized by Bruce D. Evans. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include #include "math.h" #define INLINE_KERNEL_TANDF #define INLINE_REM_PIO2F #include "math_private.h" #include "e_rem_pio2f.c" #include "k_tanf.c" /* Small multiples of pi/2 rounded to double precision. */ static const double t1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ t2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ t3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ t4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ float tanf(float x) { double y; int32_t n, hx, ix; GET_FLOAT_WORD(hx,x); ix = hx & 0x7fffffff; if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ if(ix<0x39800000) /* |x| < 2**-12 */ if(((int)x)==0) return x; /* x with inexact if x != 0 */ return __kernel_tandf(x,1); } if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */ if(ix<=0x4016cbe3) /* |x| ~<= 3pi/4 */ return __kernel_tandf(x + (hx>0 ? -t1pio2 : t1pio2), -1); else return __kernel_tandf(x + (hx>0 ? -t2pio2 : t2pio2), 1); } if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */ if(ix<=0x40afeddf) /* |x| ~<= 7*pi/4 */ return __kernel_tandf(x + (hx>0 ? -t3pio2 : t3pio2), -1); else return __kernel_tandf(x + (hx>0 ? -t4pio2 : t4pio2), 1); } /* tan(Inf or NaN) is NaN */ else if (ix>=0x7f800000) return x-x; /* general argument reduction needed */ else { n = __ieee754_rem_pio2f(x,&y); /* integer parameter: 1 -- n even; -1 -- n odd */ return __kernel_tandf(y,1-((n&1)<<1)); } } diff --git a/lib/msun/src/s_tanh.c b/lib/msun/src/s_tanh.c index 1dbd1d4630eb..ce3672472186 100644 --- a/lib/msun/src/s_tanh.c +++ b/lib/msun/src/s_tanh.c @@ -1,82 +1,81 @@ /* @(#)s_tanh.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* Tanh(x) * Return the Hyperbolic Tangent of x * * Method : * x -x * e - e * 0. tanh(x) is defined to be ----------- * x -x * e + e * 1. reduce x to non-negative by tanh(-x) = -tanh(x). * 2. 0 <= x < 2**-28 : tanh(x) := x with inexact if x != 0 * -t * 2**-28 <= x < 1 : tanh(x) := -----; t = expm1(-2x) * t + 2 * 2 * 1 <= x < 22 : tanh(x) := 1 - -----; t = expm1(2x) * t + 2 * 22 <= x <= INF : tanh(x) := 1. * * Special cases: * tanh(NaN) is NaN; * only tanh(0)=0 is exact for finite argument. */ #include #include "math.h" #include "math_private.h" static const volatile double tiny = 1.0e-300; static const double one = 1.0, two = 2.0, huge = 1.0e300; double tanh(double x) { double t,z; int32_t jx,ix; GET_HIGH_WORD(jx,x); ix = jx&0x7fffffff; /* 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| < 22 */ if (ix < 0x40360000) { /* |x|<22 */ if (ix<0x3e300000) { /* |x|<2**-28 */ if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */ } if (ix>=0x3ff00000) { /* |x|>=1 */ t = expm1(two*fabs(x)); z = one - two/(t+two); } else { t = expm1(-two*fabs(x)); z= -t/(t+two); } /* |x| >= 22, return +-1 */ } else { z = one - tiny; /* raise inexact flag */ } return (jx>=0)? z: -z; } #if (LDBL_MANT_DIG == 53) __weak_reference(tanh, tanhl); #endif diff --git a/lib/msun/src/s_tanhf.c b/lib/msun/src/s_tanhf.c index 986404f52f5a..e56813adfdc2 100644 --- a/lib/msun/src/s_tanhf.c +++ b/lib/msun/src/s_tanhf.c @@ -1,55 +1,54 @@ /* s_tanhf.c -- float version of s_tanh.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include #include "math.h" #include "math_private.h" static const volatile float tiny = 1.0e-30; static const float one=1.0, two=2.0, huge = 1.0e30; float tanhf(float x) { float t,z; int32_t jx,ix; GET_FLOAT_WORD(jx,x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7f800000) { if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ else return one/x-one; /* tanh(NaN) = NaN */ } /* |x| < 9 */ if (ix < 0x41100000) { /* |x|<9 */ if (ix<0x39800000) { /* |x|<2**-12 */ if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */ } if (ix>=0x3f800000) { /* |x|>=1 */ t = expm1f(two*fabsf(x)); z = one - two/(t+two); } else { t = expm1f(-two*fabsf(x)); z= -t/(t+two); } /* |x| >= 9, return +-1 */ } else { z = one - tiny; /* raise inexact flag */ } return (jx>=0)? z: -z; } diff --git a/lib/msun/src/s_tanhl.c b/lib/msun/src/s_tanhl.c index 3ee5b50bd2c8..30305c9a112d 100644 --- a/lib/msun/src/s_tanhl.c +++ b/lib/msun/src/s_tanhl.c @@ -1,172 +1,171 @@ /* from: FreeBSD: head/lib/msun/src/s_tanhl.c XXX */ /* @(#)s_tanh.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * See s_tanh.c for complete comments. * * Converted to long double by Bruce D. Evans. */ #include #ifdef __i386__ #include #endif #include "math.h" #include "math_private.h" #include "fpmath.h" #include "k_expl.h" #if LDBL_MAX_EXP != 0x4000 /* We also require the usual expsign encoding. */ #error "Unsupported long double format" #endif #define BIAS (LDBL_MAX_EXP - 1) static const volatile double tiny = 1.0e-300; static const double one = 1.0; #if LDBL_MANT_DIG == 64 /* * Domain [-0.25, 0.25], range ~[-1.6304e-22, 1.6304e-22]: * |tanh(x)/x - t(x)| < 2**-72.3 */ static const union IEEEl2bits T3u = LD80C(0xaaaaaaaaaaaaaa9f, -2, -3.33333333333333333017e-1L); #define T3 T3u.e static const double T5 = 1.3333333333333314e-1, /* 0x1111111111110a.0p-55 */ T7 = -5.3968253968210485e-2, /* -0x1ba1ba1ba1a1a1.0p-57 */ T9 = 2.1869488531393817e-2, /* 0x1664f488172022.0p-58 */ T11 = -8.8632352345964591e-3, /* -0x1226e34bc138d5.0p-59 */ T13 = 3.5921169709993771e-3, /* 0x1d6d371d3e400f.0p-61 */ T15 = -1.4555786415756001e-3, /* -0x17d923aa63814d.0p-62 */ T17 = 5.8645267876296793e-4, /* 0x13378589b85aa7.0p-63 */ T19 = -2.1121033571392224e-4; /* -0x1baf0af80c4090.0p-65 */ #elif LDBL_MANT_DIG == 113 /* * Domain [-0.25, 0.25], range ~[-2.4211e-37, 2.4211e-37]: * |tanh(x)/x - t(x)| < 2**121.6 */ static const long double T3 = -3.33333333333333333333333333333332980e-1L, /* -0x1555555555555555555555555554e.0p-114L */ T5 = 1.33333333333333333333333333332707260e-1L, /* 0x1111111111111111111111110ab7b.0p-115L */ T7 = -5.39682539682539682539682535723482314e-2L, /* -0x1ba1ba1ba1ba1ba1ba1ba17b5fc98.0p-117L */ T9 = 2.18694885361552028218693591149061717e-2L, /* 0x1664f4882c10f9f32d6b1a12a25e5.0p-118L */ T11 = -8.86323552990219656883762347736381851e-3L, /* -0x1226e355e6c23c8f5a5a0f386cb4d.0p-119L */ T13 = 3.59212803657248101358314398220822722e-3L, /* 0x1d6d3d0e157ddfb403ad3637442c6.0p-121L */ T15 = -1.45583438705131796512568010348874662e-3L; /* -0x17da36452b75e150c44cc34253b34.0p-122L */ static const double T17 = 5.9002744094556621e-4, /* 0x1355824803668e.0p-63 */ T19 = -2.3912911424260516e-4, /* -0x1f57d7734c8dde.0p-65 */ T21 = 9.6915379535512898e-5, /* 0x1967e18ad6a6ca.0p-66 */ T23 = -3.9278322983156353e-5, /* -0x1497d8e6b75729.0p-67 */ T25 = 1.5918887220143869e-5, /* 0x10b1319998cafa.0p-68 */ T27 = -6.4514295231630956e-6, /* -0x1b0f2b71b218eb.0p-70 */ T29 = 2.6120754043964365e-6, /* 0x15e963a3cf3a39.0p-71 */ T31 = -1.0407567231003314e-6, /* -0x1176041e656869.0p-72 */ T33 = 3.4744117554063574e-7; /* 0x1750fe732cab9c.0p-74 */ #endif /* LDBL_MANT_DIG == 64 */ static inline long double divl(long double a, long double b, long double c, long double d, long double e, long double f) { long double inv, r; float fr, fw; _2sumF(a, c); b = b + c; _2sumF(d, f); e = e + f; inv = 1 / (d + e); r = (a + b) * inv; fr = r; r = fr; fw = d + e; e = d - fw + e; d = fw; r = r + (a - d * r + b - e * r) * inv; return r; } long double tanhl(long double x) { long double hi,lo,s,x2,x4,z; #if LDBL_MANT_DIG == 113 double dx2; #endif int16_t jx,ix; GET_LDBL_EXPSIGN(jx,x); ix = jx&0x7fff; /* x is INF or NaN */ if(ix>=0x7fff) { if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ else return one/x-one; /* tanh(NaN) = NaN */ } ENTERI(); /* |x| < 40 */ if (ix < 0x4004 || fabsl(x) < 40) { /* |x|<40 */ if (__predict_false(ix= 40, return +-1 */ } else { z = one - tiny; /* raise inexact flag */ } s = 1; if (jx<0) s = -1; RETURNI(s*z); } diff --git a/lib/msun/src/s_tanl.c b/lib/msun/src/s_tanl.c index 1e9d7263c289..3736477922dc 100644 --- a/lib/msun/src/s_tanl.c +++ b/lib/msun/src/s_tanl.c @@ -1,95 +1,94 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 Steven G. Kargl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include /* * Limited testing on pseudorandom numbers drawn within [0:4e8] shows * an accuracy of <= 1.5 ULP where 247024 values of x out of 40 million * possibles resulted in tan(x) that exceeded 0.5 ULP (ie., 0.6%). */ #include #ifdef __i386__ #include #endif #include "math.h" #include "math_private.h" #if LDBL_MANT_DIG == 64 #include "../ld80/e_rem_pio2l.h" #elif LDBL_MANT_DIG == 113 #include "../ld128/e_rem_pio2l.h" #else #error "Unsupported long double format" #endif long double tanl(long double x) { union IEEEl2bits z; int e0, s; long double y[2]; long double hi, lo; z.e = x; s = z.bits.sign; z.bits.sign = 0; /* If x = +-0 or x is subnormal, then tan(x) = x. */ if (z.bits.exp == 0) return (x); /* If x = NaN or Inf, then tan(x) = NaN. */ if (z.bits.exp == 32767) return ((x - x) / (x - x)); ENTERI(); /* Optimize the case where x is already within range. */ if (z.e < M_PI_4) { hi = __kernel_tanl(z.e, 0, 0); RETURNI(s ? -hi : hi); } e0 = __ieee754_rem_pio2l(x, y); hi = y[0]; lo = y[1]; switch (e0 & 3) { case 0: case 2: hi = __kernel_tanl(hi, lo, 0); break; case 1: case 3: hi = __kernel_tanl(hi, lo, 1); break; } RETURNI(hi); } diff --git a/lib/msun/src/s_tgammaf.c b/lib/msun/src/s_tgammaf.c index 3bf937ce958d..9fa9df9ece72 100644 --- a/lib/msun/src/s_tgammaf.c +++ b/lib/msun/src/s_tgammaf.c @@ -1,43 +1,42 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include /* * We simply call tgamma() rather than bloating the math library with * a float-optimized version of it. The reason is that tgammaf() is * essentially useless, since the function is superexponential and * floats have very limited range. */ float tgammaf(float x) { return (tgamma(x)); } diff --git a/lib/msun/src/s_trunc.c b/lib/msun/src/s_trunc.c index 4bd1249544ea..a0bdba5f1fa9 100644 --- a/lib/msun/src/s_trunc.c +++ b/lib/msun/src/s_trunc.c @@ -1,65 +1,64 @@ /* @(#)s_floor.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * trunc(x) * Return x rounded toward 0 to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to trunc(x). */ #include #include "math.h" #include "math_private.h" static const double huge = 1.0e300; double trunc(double x) { int32_t i0,i1,j0; u_int32_t i; EXTRACT_WORDS(i0,i1,x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0) {/* |x|<1, so return 0*sign(x) */ i0 &= 0x80000000U; i1 = 0; } } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ i0 &= (~i); i1=0; } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((u_int32_t)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ if(huge+x>0.0) /* raise inexact flag */ i1 &= (~i); } INSERT_WORDS(x,i0,i1); return x; } #if LDBL_MANT_DIG == 53 __weak_reference(trunc, truncl); #endif diff --git a/lib/msun/src/s_truncf.c b/lib/msun/src/s_truncf.c index 8d15c78d69da..d1db49c790a8 100644 --- a/lib/msun/src/s_truncf.c +++ b/lib/msun/src/s_truncf.c @@ -1,51 +1,50 @@ /* @(#)s_floor.c 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ -#include /* * truncf(x) * Return x rounded toward 0 to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to truncf(x). */ #include "math.h" #include "math_private.h" static const float huge = 1.0e30F; float truncf(float x) { int32_t i0,j0; u_int32_t i; GET_FLOAT_WORD(i0,x); j0 = ((i0>>23)&0xff)-0x7f; if(j0<23) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0F) /* |x|<1, so return 0*sign(x) */ i0 &= 0x80000000; } else { i = (0x007fffff)>>j0; if((i0&i)==0) return x; /* x is integral */ if(huge+x>0.0F) /* raise inexact flag */ i0 &= (~i); } } else { if(j0==0x80) return x+x; /* inf or NaN */ else return x; /* x is integral */ } SET_FLOAT_WORD(x,i0); return x; } diff --git a/lib/msun/src/s_truncl.c b/lib/msun/src/s_truncl.c index f54608ac7ab0..3a2eb0908f88 100644 --- a/lib/msun/src/s_truncl.c +++ b/lib/msun/src/s_truncl.c @@ -1,66 +1,65 @@ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * From: @(#)s_floor.c 5.1 93/09/24 */ -#include /* * truncl(x) * Return x rounded toward 0 to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to truncl(x). */ #include #include #include #include "fpmath.h" #ifdef LDBL_IMPLICIT_NBIT #define MANH_SIZE (LDBL_MANH_SIZE + 1) #else #define MANH_SIZE LDBL_MANH_SIZE #endif static const long double huge = 1.0e300; static const float zero[] = { 0.0, -0.0 }; long double truncl(long double x) { union IEEEl2bits u = { .e = x }; int e = u.bits.exp - LDBL_MAX_EXP + 1; if (e < MANH_SIZE - 1) { if (e < 0) { /* raise inexact if x != 0 */ if (huge + x > 0.0) u.e = zero[u.bits.sign]; } else { uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); if (((u.bits.manh & m) | u.bits.manl) == 0) return (x); /* x is integral */ if (huge + x > 0.0) { /* raise inexact flag */ u.bits.manh &= ~m; u.bits.manl = 0; } } } else if (e < LDBL_MANT_DIG - 1) { uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); if ((u.bits.manl & m) == 0) return (x); /* x is integral */ if (huge + x > 0.0) /* raise inexact flag */ u.bits.manl &= ~m; } return (u.e); } diff --git a/lib/msun/src/w_cabs.c b/lib/msun/src/w_cabs.c index dfae649b9906..49864619b072 100644 --- a/lib/msun/src/w_cabs.c +++ b/lib/msun/src/w_cabs.c @@ -1,21 +1,20 @@ /* * cabs() wrapper for hypot(). * * Written by J.T. Conklin, * Placed into the Public Domain, 1994. */ -#include #include #include #include double cabs(double complex z) { return hypot(creal(z), cimag(z)); } #if LDBL_MANT_DIG == 53 __weak_reference(cabs, cabsl); #endif diff --git a/lib/msun/src/w_cabsl.c b/lib/msun/src/w_cabsl.c index 943413c31106..1539944faf6c 100644 --- a/lib/msun/src/w_cabsl.c +++ b/lib/msun/src/w_cabsl.c @@ -1,18 +1,17 @@ /* * cabs() wrapper for hypot(). * * Written by J.T. Conklin, * Placed into the Public Domain, 1994. * * Modified by Steven G. Kargl for the long double type. */ -#include #include #include long double cabsl(long double complex z) { return hypotl(creall(z), cimagl(z)); } diff --git a/lib/msun/tests/rem_test.c b/lib/msun/tests/rem_test.c index 9e5b8c302948..c96dc5ecd074 100644 --- a/lib/msun/tests/rem_test.c +++ b/lib/msun/tests/rem_test.c @@ -1,212 +1,211 @@ /*- * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test for remainder functions: remainder, remainderf, remainderl, * remquo, remquof, and remquol. * Missing tests: fmod, fmodf. */ -#include #include #include #include #include #include #include "test-utils.h" static void test_invalid(long double, long double); static void testl(long double, long double, long double, int); static void testd(double, double, double, int); static void testf(float, float, float, int); #define test(x, y, e_r, e_q) do { \ testl(x, y, e_r, e_q); \ testd(x, y, e_r, e_q); \ testf(x, y, e_r, e_q); \ } while (0) ATF_TC_WITHOUT_HEAD(rem1); ATF_TC_BODY(rem1, tc) { test_invalid(0.0, 0.0); test_invalid(1.0, 0.0); test_invalid(INFINITY, 0.0); test_invalid(INFINITY, 1.0); test_invalid(-INFINITY, 1.0); test_invalid(NAN, 1.0); test_invalid(1.0, NAN); test(4, 4, 0, 1); test(0, 3.0, 0, 0); testd(0x1p-1074, 1, 0x1p-1074, 0); testf(0x1p-149, 1, 0x1p-149, 0); test(3.0, 4, -1, 1); test(3.0, -4, -1, -1); testd(275 * 1193040, 275, 0, 1193040); test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */ testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1); #if LDBL_MANT_DIG > 53 testl(-0x1.23456789abcdefp-2000L, 0x1.fedcba987654321p-2000L, 0x1.b72ea61d950c862p-2001L, -1); #endif } ATF_TC_WITHOUT_HEAD(rem2); ATF_TC_BODY(rem2, tc) { /* * The actual quotient here is 864062210.50000003..., but * double-precision division gets -8.64062210.5, which rounds * the wrong way. This test ensures that remquo() is smart * enough to get the low-order bit right. */ testd(-0x1.98260f22fc6dep-302, 0x1.fb3167c430a13p-332, 0x1.fb3165b82de72p-333, -864062211); /* Even harder cases with greater exponent separation */ test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577); testd(-0x1.abcdefp120, 0x1.87654321p-120, -0x1.69c78ec4p-121, -63816414); } ATF_TC_WITHOUT_HEAD(rem3); ATF_TC_BODY(rem3, tc) { test(0x1.66666cp+120, 0x1p+71, 0.0, 1476395008); testd(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testl(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testd(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); testl(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); } static void test_invalid(long double x, long double y) { int q; q = 0xdeadbeef; ATF_CHECK(isnan(remainder(x, y))); ATF_CHECK(isnan(remquo(x, y, &q))); #ifdef STRICT ATF_CHECK(q == 0xdeadbeef); #endif ATF_CHECK(isnan(remainderf(x, y))); ATF_CHECK(isnan(remquof(x, y, &q))); #ifdef STRICT ATF_CHECK(q == 0xdeadbeef); #endif ATF_CHECK(isnan(remainderl(x, y))); ATF_CHECK(isnan(remquol(x, y, &q))); #ifdef STRICT ATF_CHECK(q == 0xdeadbeef); #endif } /* 0x012345 ==> 0x01ffff */ static inline int mask(int x) { return ((unsigned)~0 >> (32 - fls(x))); } static void testl(long double x, long double y, long double expected_rem, int expected_quo) { int q; long double rem; q = random(); rem = remainderl(x, y); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); rem = remquol(x, y, &q); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { ATF_CHECK((q > 0) ^ !(expected_quo > 0)); q = abs(q); ATF_CHECK(q == (abs(expected_quo) & mask(q))); } } static void testd(double x, double y, double expected_rem, int expected_quo) { int q; double rem; q = random(); rem = remainder(x, y); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); rem = remquo(x, y, &q); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { ATF_CHECK((q > 0) ^ !(expected_quo > 0)); q = abs(q); ATF_CHECK(q == (abs(expected_quo) & mask(q))); } } static void testf(float x, float y, float expected_rem, int expected_quo) { int q; float rem; q = random(); rem = remainderf(x, y); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); rem = remquof(x, y, &q); ATF_CHECK(rem == expected_rem); ATF_CHECK(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { ATF_CHECK((q > 0) ^ !(expected_quo > 0)); q = abs(q); ATF_CHECK((q & mask(q)) == (abs(expected_quo) & mask(q))); } } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, rem1); ATF_TP_ADD_TC(tp, rem2); ATF_TP_ADD_TC(tp, rem3); return (atf_no_error()); }