]> git.ipfire.org Git - thirdparty/gcc.git/blame - libquadmath/math/expm1q.c
tree-optimization/95495 - use SLP_TREE_REPRESENTATIVE in assertion
[thirdparty/gcc.git] / libquadmath / math / expm1q.c
CommitLineData
4239f144 1/* expm1q.c
1ec601bf
FXC
2 *
3 * Exponential function, minus 1
4239f144 4 * 128-bit long double precision
1ec601bf
FXC
5 *
6 *
7 *
8 * SYNOPSIS:
9 *
4239f144 10 * long double x, y, expm1q();
1ec601bf 11 *
4239f144 12 * y = expm1q( x );
1ec601bf
FXC
13 *
14 *
15 *
16 * DESCRIPTION:
17 *
18 * Returns e (2.71828...) raised to the x power, minus one.
19 *
20 * Range reduction is accomplished by separating the argument
21 * into an integer k and fraction f such that
22 *
23 * x k f
24 * e = 2 e.
25 *
26 * An expansion x + .5 x^2 + x^3 R(x) approximates exp(f) - 1
27 * in the basic range [-0.5 ln 2, 0.5 ln 2].
28 *
29 *
30 * ACCURACY:
31 *
32 * Relative error:
33 * arithmetic domain # trials peak rms
34 * IEEE -79,+MAXLOG 100,000 1.7e-34 4.5e-35
35 *
36 */
37
1eba0867 38/* Copyright 2001 by Stephen L. Moshier
1ec601bf
FXC
39
40 This library is free software; you can redistribute it and/or
41 modify it under the terms of the GNU Lesser General Public
42 License as published by the Free Software Foundation; either
43 version 2.1 of the License, or (at your option) any later version.
44
45 This library is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48 Lesser General Public License for more details.
49
50 You should have received a copy of the GNU Lesser General Public
4239f144
JM
51 License along with this library; if not, see
52 <http://www.gnu.org/licenses/>. */
1ec601bf 53
1ec601bf
FXC
54#include "quadmath-imp.h"
55
56/* exp(x) - 1 = x + 0.5 x^2 + x^3 P(x)/Q(x)
57 -.5 ln 2 < x < .5 ln 2
58 Theoretical peak relative error = 8.1e-36 */
59
60static const __float128
61 P0 = 2.943520915569954073888921213330863757240E8Q,
62 P1 = -5.722847283900608941516165725053359168840E7Q,
63 P2 = 8.944630806357575461578107295909719817253E6Q,
64 P3 = -7.212432713558031519943281748462837065308E5Q,
65 P4 = 4.578962475841642634225390068461943438441E4Q,
66 P5 = -1.716772506388927649032068540558788106762E3Q,
67 P6 = 4.401308817383362136048032038528753151144E1Q,
68 P7 = -4.888737542888633647784737721812546636240E-1Q,
69 Q0 = 1.766112549341972444333352727998584753865E9Q,
70 Q1 = -7.848989743695296475743081255027098295771E8Q,
71 Q2 = 1.615869009634292424463780387327037251069E8Q,
72 Q3 = -2.019684072836541751428967854947019415698E7Q,
73 Q4 = 1.682912729190313538934190635536631941751E6Q,
74 Q5 = -9.615511549171441430850103489315371768998E4Q,
75 Q6 = 3.697714952261803935521187272204485251835E3Q,
76 Q7 = -8.802340681794263968892934703309274564037E1Q,
77 /* Q8 = 1.000000000000000000000000000000000000000E0 */
78/* C1 + C2 = ln 2 */
79
80 C1 = 6.93145751953125E-1Q,
81 C2 = 1.428606820309417232121458176568075500134E-6Q,
1ec601bf 82/* ln 2^-114 */
4239f144 83 minarg = -7.9018778583833765273564461846232128760607E1Q, big = 1e4932Q;
1ec601bf
FXC
84
85
86__float128
87expm1q (__float128 x)
88{
89 __float128 px, qx, xx;
90 int32_t ix, sign;
91 ieee854_float128 u;
92 int k;
93
94 /* Detect infinity and NaN. */
95 u.value = x;
96 ix = u.words32.w0;
97 sign = ix & 0x80000000;
98 ix &= 0x7fffffff;
737df6e6
TB
99 if (!sign && ix >= 0x40060000)
100 {
101 /* If num is positive and exp >= 6 use plain exp. */
102 return expq (x);
103 }
1ec601bf
FXC
104 if (ix >= 0x7fff0000)
105 {
1eba0867 106 /* Infinity (which must be negative infinity). */
1ec601bf 107 if (((ix & 0xffff) | u.words32.w1 | u.words32.w2 | u.words32.w3) == 0)
4239f144 108 return -1;
1eba0867
JJ
109 /* NaN. Invalid exception if signaling. */
110 return x + x;
1ec601bf
FXC
111 }
112
113 /* expm1(+- 0) = +- 0. */
114 if ((ix == 0) && (u.words32.w1 | u.words32.w2 | u.words32.w3) == 0)
115 return x;
116
1ec601bf
FXC
117 /* Minimum value. */
118 if (x < minarg)
4239f144 119 return (4.0/big - 1);
1ec601bf 120
1eba0867
JJ
121 /* Avoid internal underflow when result does not underflow, while
122 ensuring underflow (without returning a zero of the wrong sign)
123 when the result does underflow. */
124 if (fabsq (x) < 0x1p-113Q)
125 {
126 math_check_force_underflow (x);
127 return x;
128 }
129
1ec601bf
FXC
130 /* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
131 xx = C1 + C2; /* ln 2. */
132 px = floorq (0.5 + x / xx);
133 k = px;
134 /* remainder times ln 2 */
135 x -= px * C1;
136 x -= px * C2;
137
138 /* Approximate exp(remainder ln 2). */
139 px = (((((((P7 * x
140 + P6) * x
141 + P5) * x + P4) * x + P3) * x + P2) * x + P1) * x + P0) * x;
142
143 qx = (((((((x
144 + Q7) * x
145 + Q6) * x + Q5) * x + Q4) * x + Q3) * x + Q2) * x + Q1) * x + Q0;
146
147 xx = x * x;
148 qx = x + (0.5 * xx + xx * px / qx);
149
150 /* exp(x) = exp(k ln 2) exp(remainder ln 2) = 2^k exp(remainder ln 2).
151
152 We have qx = exp(remainder ln 2) - 1, so
153 exp(x) - 1 = 2^k (qx + 1) - 1
154 = 2^k qx + 2^k - 1. */
155
4239f144 156 px = ldexpq (1, k);
1ec601bf
FXC
157 x = px * qx + (px - 1.0);
158 return x;
159}