1*03a88e3dSMark Murray /*-
2*03a88e3dSMark Murray * SPDX-License-Identifier: BSD-3-Clause
3*03a88e3dSMark Murray *
4*03a88e3dSMark Murray * Copyright (c) 1985, 1993
5*03a88e3dSMark Murray * The Regents of the University of California. All rights reserved.
6*03a88e3dSMark Murray *
7*03a88e3dSMark Murray * Redistribution and use in source and binary forms, with or without
8*03a88e3dSMark Murray * modification, are permitted provided that the following conditions
9*03a88e3dSMark Murray * are met:
10*03a88e3dSMark Murray * 1. Redistributions of source code must retain the above copyright
11*03a88e3dSMark Murray * notice, this list of conditions and the following disclaimer.
12*03a88e3dSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
13*03a88e3dSMark Murray * notice, this list of conditions and the following disclaimer in the
14*03a88e3dSMark Murray * documentation and/or other materials provided with the distribution.
15*03a88e3dSMark Murray * 3. Neither the name of the University nor the names of its contributors
16*03a88e3dSMark Murray * may be used to endorse or promote products derived from this software
17*03a88e3dSMark Murray * without specific prior written permission.
18*03a88e3dSMark Murray *
19*03a88e3dSMark Murray * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*03a88e3dSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*03a88e3dSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*03a88e3dSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*03a88e3dSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*03a88e3dSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*03a88e3dSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*03a88e3dSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*03a88e3dSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*03a88e3dSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*03a88e3dSMark Murray * SUCH DAMAGE.
30*03a88e3dSMark Murray */
31*03a88e3dSMark Murray
32*03a88e3dSMark Murray /*
33*03a88e3dSMark Murray * See bsdsrc/b_exp.c for implementation details.
34*03a88e3dSMark Murray *
35*03a88e3dSMark Murray * bsdrc/b_exp.c converted to long double by Steven G. Kargl.
36*03a88e3dSMark Murray */
37*03a88e3dSMark Murray
38*03a88e3dSMark Murray #include "fpmath.h"
39*03a88e3dSMark Murray #include "math_private.h"
40*03a88e3dSMark Murray
41*03a88e3dSMark Murray static const union IEEEl2bits
42*03a88e3dSMark Murray p0u = LD80C(0xaaaaaaaaaaaaaaab, -3, 1.66666666666666666671e-01L),
43*03a88e3dSMark Murray p1u = LD80C(0xb60b60b60b60b59a, -9, -2.77777777777777775377e-03L),
44*03a88e3dSMark Murray p2u = LD80C(0x8ab355e008a3cfce, -14, 6.61375661375629297465e-05L),
45*03a88e3dSMark Murray p3u = LD80C(0xddebbc994b0c1376, -20, -1.65343915327882529784e-06L),
46*03a88e3dSMark Murray p4u = LD80C(0xb354784cb4ef4c41, -25, 4.17535101591534118469e-08L),
47*03a88e3dSMark Murray p5u = LD80C(0x913e8a718382ce75, -30, -1.05679137034774806475e-09L),
48*03a88e3dSMark Murray p6u = LD80C(0xe8f0042aa134502e, -36, 2.64819349895429516863e-11L);
49*03a88e3dSMark Murray #define p1 (p0u.e)
50*03a88e3dSMark Murray #define p2 (p1u.e)
51*03a88e3dSMark Murray #define p3 (p2u.e)
52*03a88e3dSMark Murray #define p4 (p3u.e)
53*03a88e3dSMark Murray #define p5 (p4u.e)
54*03a88e3dSMark Murray #define p6 (p5u.e)
55*03a88e3dSMark Murray #define p7 (p6u.e)
56*03a88e3dSMark Murray
57*03a88e3dSMark Murray /*
58*03a88e3dSMark Murray * lnhuge = (LDBL_MAX_EXP + 9) * log(2.)
59*03a88e3dSMark Murray * lntiny = (LDBL_MIN_EXP - 64 - 10) * log(2.)
60*03a88e3dSMark Murray * invln2 = 1 / log(2.)
61*03a88e3dSMark Murray */
62*03a88e3dSMark Murray static const union IEEEl2bits
63*03a88e3dSMark Murray ln2hiu = LD80C(0xb17217f700000000, -1, 6.93147180369123816490e-01L),
64*03a88e3dSMark Murray ln2lou = LD80C(0xd1cf79abc9e3b398, -33, 1.90821492927058781614e-10L),
65*03a88e3dSMark Murray lnhugeu = LD80C(0xb18b0c0330a8fad9, 13, 1.13627617309191834574e+04L),
66*03a88e3dSMark Murray lntinyu = LD80C(0xb236f28a68bc3bd7, 13, -1.14057368561139000667e+04L),
67*03a88e3dSMark Murray invln2u = LD80C(0xb8aa3b295c17f0bc, 0, 1.44269504088896340739e+00L);
68*03a88e3dSMark Murray #define ln2hi (ln2hiu.e)
69*03a88e3dSMark Murray #define ln2lo (ln2lou.e)
70*03a88e3dSMark Murray #define lnhuge (lnhugeu.e)
71*03a88e3dSMark Murray #define lntiny (lntinyu.e)
72*03a88e3dSMark Murray #define invln2 (invln2u.e)
73*03a88e3dSMark Murray
74*03a88e3dSMark Murray /* returns exp(r = x + c) for |c| < |x| with no overlap. */
75*03a88e3dSMark Murray
76*03a88e3dSMark Murray static long double
__exp__D(long double x,long double c)77*03a88e3dSMark Murray __exp__D(long double x, long double c)
78*03a88e3dSMark Murray {
79*03a88e3dSMark Murray long double hi, lo, z;
80*03a88e3dSMark Murray int k;
81*03a88e3dSMark Murray
82*03a88e3dSMark Murray if (x != x) /* x is NaN. */
83*03a88e3dSMark Murray return(x);
84*03a88e3dSMark Murray
85*03a88e3dSMark Murray if (x <= lnhuge) {
86*03a88e3dSMark Murray if (x >= lntiny) {
87*03a88e3dSMark Murray /* argument reduction: x --> x - k*ln2 */
88*03a88e3dSMark Murray z = invln2 * x;
89*03a88e3dSMark Murray k = z + copysignl(0.5L, x);
90*03a88e3dSMark Murray
91*03a88e3dSMark Murray /*
92*03a88e3dSMark Murray * Express (x + c) - k * ln2 as hi - lo.
93*03a88e3dSMark Murray * Let x = hi - lo rounded.
94*03a88e3dSMark Murray */
95*03a88e3dSMark Murray hi = x - k * ln2hi; /* Exact. */
96*03a88e3dSMark Murray lo = k * ln2lo - c;
97*03a88e3dSMark Murray x = hi - lo;
98*03a88e3dSMark Murray
99*03a88e3dSMark Murray /* Return 2^k*[1+x+x*c/(2+c)] */
100*03a88e3dSMark Murray z = x * x;
101*03a88e3dSMark Murray c = x - z * (p1 + z * (p2 + z * (p3 + z * (p4 +
102*03a88e3dSMark Murray z * (p5 + z * (p6 + z * p7))))));
103*03a88e3dSMark Murray c = (x * c) / (2 - c);
104*03a88e3dSMark Murray
105*03a88e3dSMark Murray return (ldexpl(1 + (hi - (lo - c)), k));
106*03a88e3dSMark Murray } else {
107*03a88e3dSMark Murray /* exp(-INF) is 0. exp(-big) underflows to 0. */
108*03a88e3dSMark Murray return (isfinite(x) ? ldexpl(1., -5000) : 0);
109*03a88e3dSMark Murray }
110*03a88e3dSMark Murray } else
111*03a88e3dSMark Murray /* exp(INF) is INF, exp(+big#) overflows to INF */
112*03a88e3dSMark Murray return (isfinite(x) ? ldexpl(1., 5000) : x);
113*03a88e3dSMark Murray }
114