e_lgammal_r.c revision 1.3 1 1.1 christos /* @(#)e_lgamma_r.c 1.3 95/01/18 */
2 1.1 christos /*
3 1.1 christos * ====================================================
4 1.1 christos * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 1.1 christos *
6 1.1 christos * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 1.1 christos * Permission to use, copy, modify, and distribute this
8 1.1 christos * software is freely granted, provided that this notice
9 1.1 christos * is preserved.
10 1.1 christos * ====================================================
11 1.1 christos */
12 1.1 christos
13 1.1 christos #include <sys/cdefs.h>
14 1.1 christos /*
15 1.1 christos * See e_lgamma_r.c for complete comments.
16 1.1 christos *
17 1.1 christos * Converted to long double by Steven G. Kargl.
18 1.1 christos */
19 1.1 christos
20 1.1 christos #include "math.h"
21 1.1 christos #include "math_private.h"
22 1.1 christos
23 1.1 christos static const volatile double vzero = 0;
24 1.1 christos
25 1.1 christos static const double
26 1.1 christos zero= 0,
27 1.1 christos half= 0.5,
28 1.1 christos one = 1;
29 1.1 christos
30 1.1 christos static const union ieee_ext_u
31 1.1 christos piu = LD80C(0xc90fdaa22168c235, 1, 3.14159265358979323851e+00L);
32 1.1 christos #define pi (piu.extu_ld)
33 1.1 christos /*
34 1.1 christos * Domain y in [0x1p-70, 0.27], range ~[-4.5264e-22, 4.5264e-22]:
35 1.1 christos * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-70.9
36 1.1 christos */
37 1.1 christos static const union ieee_ext_u
38 1.1 christos a0u = LD80C(0x9e233f1bed863d26, -4, 7.72156649015328606028e-02L),
39 1.1 christos a1u = LD80C(0xa51a6625307d3249, -2, 3.22467033424113218889e-01L),
40 1.1 christos a2u = LD80C(0x89f000d2abafda8c, -4, 6.73523010531979398946e-02L),
41 1.1 christos a3u = LD80C(0xa8991563eca75f26, -6, 2.05808084277991211934e-02L),
42 1.1 christos a4u = LD80C(0xf2027e10634ce6b6, -8, 7.38555102796070454026e-03L),
43 1.1 christos a5u = LD80C(0xbd6eb76dd22187f4, -9, 2.89051035162703932972e-03L),
44 1.1 christos a6u = LD80C(0x9c562ab05e0458ed, -10, 1.19275351624639999297e-03L),
45 1.1 christos a7u = LD80C(0x859baed93ee48e46, -11, 5.09674593842117925320e-04L),
46 1.1 christos a8u = LD80C(0xe9f28a4432949af2, -13, 2.23109648015769155122e-04L),
47 1.1 christos a9u = LD80C(0xd12ad0d9b93c6bb0, -14, 9.97387167479808509830e-05L),
48 1.1 christos a10u= LD80C(0xb7522643c78a219b, -15, 4.37071076331030136818e-05L),
49 1.1 christos a11u= LD80C(0xca024dcdece2cb79, -16, 2.40813493372040143061e-05L),
50 1.1 christos a12u= LD80C(0xbb90fb6968ebdbf9, -19, 2.79495621083634031729e-06L),
51 1.1 christos a13u= LD80C(0xba1c9ffeeae07b37, -17, 1.10931287015513924136e-05L);
52 1.1 christos #define a0 (a0u.extu_ld)
53 1.1 christos #define a1 (a1u.extu_ld)
54 1.1 christos #define a2 (a2u.extu_ld)
55 1.1 christos #define a3 (a3u.extu_ld)
56 1.1 christos #define a4 (a4u.extu_ld)
57 1.1 christos #define a5 (a5u.extu_ld)
58 1.1 christos #define a6 (a6u.extu_ld)
59 1.1 christos #define a7 (a7u.extu_ld)
60 1.1 christos #define a8 (a8u.extu_ld)
61 1.1 christos #define a9 (a9u.extu_ld)
62 1.1 christos #define a10 (a10u.extu_ld)
63 1.1 christos #define a11 (a11u.extu_ld)
64 1.1 christos #define a12 (a12u.extu_ld)
65 1.1 christos #define a13 (a13u.extu_ld)
66 1.1 christos /*
67 1.1 christos * Domain x in [tc-0.24, tc+0.28], range ~[-6.1205e-22, 6.1205e-22]:
68 1.1 christos * |(lgamma(x) - tf) - t(x - tc)| < 2**-70.5
69 1.1 christos */
70 1.1 christos static const union ieee_ext_u
71 1.1 christos tcu = LD80C(0xbb16c31ab5f1fb71, 0, 1.46163214496836234128e+00L),
72 1.1 christos tfu = LD80C(0xf8cdcde61c520e0f, -4, -1.21486290535849608093e-01L),
73 1.1 christos ttu = LD80C(0xd46ee54b27d4de99, -69, -2.81152980996018785880e-21L),
74 1.1 christos t0u = LD80C(0x80b9406556a62a6b, -68, 3.40728634996055147231e-21L),
75 1.1 christos t1u = LD80C(0xc7e9c6f6df3f8c39, -67, -1.05833162742737073665e-20L),
76 1.1 christos t2u = LD80C(0xf7b95e4771c55d51, -2, 4.83836122723810583532e-01L),
77 1.1 christos t3u = LD80C(0x97213c6e35e119ff, -3, -1.47587722994530691476e-01L),
78 1.1 christos t4u = LD80C(0x845a14a6a81dc94b, -4, 6.46249402389135358063e-02L),
79 1.1 christos t5u = LD80C(0x864d46fa89997796, -5, -3.27885410884846056084e-02L),
80 1.1 christos t6u = LD80C(0x93373cbd00297438, -6, 1.79706751150707171293e-02L),
81 1.1 christos t7u = LD80C(0xa8fcfca7eddc8d1d, -7, -1.03142230361450732547e-02L),
82 1.1 christos t8u = LD80C(0xc7e7015ff4bc45af, -8, 6.10053603296546099193e-03L),
83 1.1 christos t9u = LD80C(0xf178d2247adc5093, -9, -3.68456964904901200152e-03L),
84 1.1 christos t10u = LD80C(0x94188d58f12e5e9f, -9, 2.25976420273774583089e-03L),
85 1.1 christos t11u = LD80C(0xb7cbaef14e1406f1, -10, -1.40224943666225639823e-03L),
86 1.1 christos t12u = LD80C(0xe63a671e6704ea4d, -11, 8.78250640744776944887e-04L),
87 1.1 christos t13u = LD80C(0x914b6c9cae61783e, -11, -5.54255012657716808811e-04L),
88 1.1 christos t14u = LD80C(0xb858f5bdb79276fe, -12, 3.51614951536825927370e-04L),
89 1.1 christos t15u = LD80C(0xea73e744c34b9591, -13, -2.23591563824520112236e-04L),
90 1.1 christos t16u = LD80C(0x99aeabb0d67ba835, -13, 1.46562869351659194136e-04L),
91 1.1 christos t17u = LD80C(0xd7c6938325db2024, -14, -1.02889866046435680588e-04L),
92 1.1 christos t18u = LD80C(0xe24cb1e3b0474775, -15, 5.39540265505221957652e-05L);
93 1.1 christos #define tc (tcu.extu_ld)
94 1.1 christos #define tf (tfu.extu_ld)
95 1.1 christos #define tt (ttu.extu_ld)
96 1.1 christos #define t0 (t0u.extu_ld)
97 1.1 christos #define t1 (t1u.extu_ld)
98 1.1 christos #define t2 (t2u.extu_ld)
99 1.1 christos #define t3 (t3u.extu_ld)
100 1.1 christos #define t4 (t4u.extu_ld)
101 1.1 christos #define t5 (t5u.extu_ld)
102 1.1 christos #define t6 (t6u.extu_ld)
103 1.1 christos #define t7 (t7u.extu_ld)
104 1.1 christos #define t8 (t8u.extu_ld)
105 1.1 christos #define t9 (t9u.extu_ld)
106 1.1 christos #define t10 (t10u.extu_ld)
107 1.1 christos #define t11 (t11u.extu_ld)
108 1.1 christos #define t12 (t12u.extu_ld)
109 1.1 christos #define t13 (t13u.extu_ld)
110 1.1 christos #define t14 (t14u.extu_ld)
111 1.1 christos #define t15 (t15u.extu_ld)
112 1.1 christos #define t16 (t16u.extu_ld)
113 1.1 christos #define t17 (t17u.extu_ld)
114 1.1 christos #define t18 (t18u.extu_ld)
115 1.1 christos /*
116 1.1 christos * Domain y in [-0.1, 0.232], range ~[-8.1938e-22, 8.3815e-22]:
117 1.1 christos * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-71.2
118 1.1 christos */
119 1.1 christos static const union ieee_ext_u
120 1.1 christos u0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
121 1.1 christos u1u = LD80C(0x98280ee45e4ddd3d, -1, 5.94361239198682739769e-01L),
122 1.1 christos u2u = LD80C(0xe330c8ead4130733, 0, 1.77492629495841234275e+00L),
123 1.1 christos u3u = LD80C(0xd4a213f1a002ec52, 0, 1.66119622514818078064e+00L),
124 1.1 christos u4u = LD80C(0xa5a9ca6f5bc62163, -1, 6.47122051417476492989e-01L),
125 1.1 christos u5u = LD80C(0xc980e49cd5b019e6, -4, 9.83903751718671509455e-02L),
126 1.1 christos u6u = LD80C(0xff636a8bdce7025b, -9, 3.89691687802305743450e-03L),
127 1.1 christos v1u = LD80C(0xbd109c533a19fbf5, 1, 2.95413883330948556544e+00L),
128 1.1 christos v2u = LD80C(0xd295cbf96f31f099, 1, 3.29039286955665403176e+00L),
129 1.1 christos v3u = LD80C(0xdab8bcfee40496cb, 0, 1.70876276441416471410e+00L),
130 1.1 christos v4u = LD80C(0xd2f2dc3638567e9f, -2, 4.12009126299534668571e-01L),
131 1.1 christos v5u = LD80C(0xa07d9b0851070f41, -5, 3.91822868305682491442e-02L),
132 1.1 christos v6u = LD80C(0xe3cd8318f7adb2c4, -11, 8.68998648222144351114e-04L);
133 1.1 christos #define u0 (u0u.extu_ld)
134 1.1 christos #define u1 (u1u.extu_ld)
135 1.1 christos #define u2 (u2u.extu_ld)
136 1.1 christos #define u3 (u3u.extu_ld)
137 1.1 christos #define u4 (u4u.extu_ld)
138 1.1 christos #define u5 (u5u.extu_ld)
139 1.1 christos #define u6 (u6u.extu_ld)
140 1.1 christos #define v1 (v1u.extu_ld)
141 1.1 christos #define v2 (v2u.extu_ld)
142 1.1 christos #define v3 (v3u.extu_ld)
143 1.1 christos #define v4 (v4u.extu_ld)
144 1.1 christos #define v5 (v5u.extu_ld)
145 1.1 christos #define v6 (v6u.extu_ld)
146 1.1 christos /*
147 1.1 christos * Domain x in (2, 3], range ~[-3.3648e-22, 3.4416e-22]:
148 1.1 christos * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-72.3
149 1.1 christos * with y = x - 2.
150 1.1 christos */
151 1.1 christos static const union ieee_ext_u
152 1.1 christos s0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
153 1.1 christos s1u = LD80C(0xd3ff0dcc7fa91f94, -3, 2.07027640921219389860e-01L),
154 1.1 christos s2u = LD80C(0xb2bb62782478ef31, -2, 3.49085881391362090549e-01L),
155 1.1 christos s3u = LD80C(0xb49f7438c4611a74, -3, 1.76389518704213357954e-01L),
156 1.1 christos s4u = LD80C(0x9a957008fa27ecf9, -5, 3.77401710862930008071e-02L),
157 1.1 christos s5u = LD80C(0xda9b389a6ca7a7ac, -9, 3.33566791452943399399e-03L),
158 1.1 christos s6u = LD80C(0xbc7a2263faf59c14, -14, 8.98728786745638844395e-05L),
159 1.1 christos r1u = LD80C(0xbf5cff5b11477d4d, 0, 1.49502555796294337722e+00L),
160 1.1 christos r2u = LD80C(0xd9aec89de08e3da6, -1, 8.50323236984473285866e-01L),
161 1.1 christos r3u = LD80C(0xeab7ae5057c443f9, -3, 2.29216312078225806131e-01L),
162 1.1 christos r4u = LD80C(0xf29707d9bd2b1e37, -6, 2.96130326586640089145e-02L),
163 1.1 christos r5u = LD80C(0xd376c2f09736c5a3, -10, 1.61334161411590662495e-03L),
164 1.1 christos r6u = LD80C(0xc985983d0cd34e3d, -16, 2.40232770710953450636e-05L),
165 1.1 christos r7u = LD80C(0xe5c7a4f7fc2ef13d, -25, -5.34997929289167573510e-08L);
166 1.1 christos #define s0 (s0u.extu_ld)
167 1.1 christos #define s1 (s1u.extu_ld)
168 1.1 christos #define s2 (s2u.extu_ld)
169 1.1 christos #define s3 (s3u.extu_ld)
170 1.1 christos #define s4 (s4u.extu_ld)
171 1.1 christos #define s5 (s5u.extu_ld)
172 1.1 christos #define s6 (s6u.extu_ld)
173 1.1 christos #define r1 (r1u.extu_ld)
174 1.1 christos #define r2 (r2u.extu_ld)
175 1.1 christos #define r3 (r3u.extu_ld)
176 1.1 christos #define r4 (r4u.extu_ld)
177 1.1 christos #define r5 (r5u.extu_ld)
178 1.1 christos #define r6 (r6u.extu_ld)
179 1.1 christos #define r7 (r7u.extu_ld)
180 1.1 christos /*
181 1.1 christos * Domain z in [8, 0x1p70], range ~[-3.0235e-22, 3.0563e-22]:
182 1.1 christos * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-71.7
183 1.1 christos */
184 1.1 christos static const union ieee_ext_u
185 1.1 christos w0u = LD80C(0xd67f1c864beb4a69, -2, 4.18938533204672741776e-01L),
186 1.1 christos w1u = LD80C(0xaaaaaaaaaaaaaaa1, -4, 8.33333333333333332678e-02L),
187 1.1 christos w2u = LD80C(0xb60b60b60b5491c9, -9, -2.77777777777760927870e-03L),
188 1.1 christos w3u = LD80C(0xd00d00cf58aede4c, -11, 7.93650793490637233668e-04L),
189 1.1 christos w4u = LD80C(0x9c09bf626783d4a5, -11, -5.95238023926039051268e-04L),
190 1.1 christos w5u = LD80C(0xdca7cadc5baa517b, -11, 8.41733700408000822962e-04L),
191 1.1 christos w6u = LD80C(0xfb060e361e1ffd07, -10, -1.91515849570245136604e-03L),
192 1.1 christos w7u = LD80C(0xcbd5101bb58d1f2b, -8, 6.22046743903262649294e-03L),
193 1.1 christos w8u = LD80C(0xad27a668d32c821b, -6, -2.11370706734662081843e-02L);
194 1.1 christos #define w0 (w0u.extu_ld)
195 1.1 christos #define w1 (w1u.extu_ld)
196 1.1 christos #define w2 (w2u.extu_ld)
197 1.1 christos #define w3 (w3u.extu_ld)
198 1.1 christos #define w4 (w4u.extu_ld)
199 1.1 christos #define w5 (w5u.extu_ld)
200 1.1 christos #define w6 (w6u.extu_ld)
201 1.1 christos #define w7 (w7u.extu_ld)
202 1.1 christos #define w8 (w8u.extu_ld)
203 1.1 christos
204 1.1 christos static long double
205 1.1 christos sin_pil(long double x)
206 1.1 christos {
207 1.1 christos volatile long double vz;
208 1.1 christos long double y,z;
209 1.1 christos uint64_t n;
210 1.1 christos uint16_t hx __unused;
211 1.1 christos
212 1.1 christos y = -x;
213 1.1 christos
214 1.1 christos vz = y+0x1p63;
215 1.1 christos z = vz-0x1p63;
216 1.1 christos if (z == y)
217 1.1 christos return zero;
218 1.1 christos
219 1.1 christos vz = y+0x1p61;
220 1.1 christos EXTRACT_LDBL80_WORDS(hx,n,vz);
221 1.1 christos z = vz-0x1p61;
222 1.1 christos if (z > y) {
223 1.1 christos z -= 0.25; /* adjust to round down */
224 1.1 christos n--;
225 1.1 christos }
226 1.1 christos n &= 7; /* octant of y mod 2 */
227 1.1 christos y = y - z + n * 0.25; /* y mod 2 */
228 1.1 christos
229 1.1 christos switch (n) {
230 1.1 christos case 0: y = __kernel_sinl(pi*y,zero,0); break;
231 1.1 christos case 1:
232 1.1 christos case 2: y = __kernel_cosl(pi*(0.5-y),zero); break;
233 1.1 christos case 3:
234 1.1 christos case 4: y = __kernel_sinl(pi*(one-y),zero,0); break;
235 1.1 christos case 5:
236 1.1 christos case 6: y = -__kernel_cosl(pi*(y-1.5),zero); break;
237 1.1 christos default: y = __kernel_sinl(pi*(y-2.0),zero,0); break;
238 1.1 christos }
239 1.1 christos return -y;
240 1.1 christos }
241 1.1 christos
242 1.1 christos long double
243 1.1 christos lgammal_r(long double x, int *signgamp)
244 1.1 christos {
245 1.3 christos long double p,p1,p2,q,r,t,w,y,z;
246 1.3 christos long double nadj = 0; // XXX: gcc
247 1.1 christos uint64_t lx;
248 1.1 christos int i;
249 1.1 christos uint16_t hx,ix;
250 1.1 christos
251 1.1 christos EXTRACT_LDBL80_WORDS(hx,lx,x);
252 1.1 christos
253 1.1 christos /* purge +-Inf and NaNs */
254 1.1 christos *signgamp = 1;
255 1.1 christos ix = hx&0x7fff;
256 1.1 christos if(ix==0x7fff) return x*x;
257 1.1 christos
258 1.1 christos ENTERI();
259 1.1 christos
260 1.1 christos /* purge +-0 and tiny arguments */
261 1.1 christos *signgamp = 1-2*(hx>>15);
262 1.1 christos if(ix<0x3fff-67) { /* |x|<2**-(p+3), return -log(|x|) */
263 1.1 christos if((ix|lx)==0)
264 1.1 christos RETURNI(one/vzero);
265 1.1 christos RETURNI(-logl(fabsl(x)));
266 1.1 christos }
267 1.1 christos
268 1.1 christos /* purge negative integers and start evaluation for other x < 0 */
269 1.1 christos if(hx&0x8000) {
270 1.1 christos *signgamp = 1;
271 1.1 christos if(ix>=0x3fff+63) /* |x|>=2**(p-1), must be -integer */
272 1.1 christos RETURNI(one/vzero);
273 1.1 christos t = sin_pil(x);
274 1.1 christos if(t==zero) RETURNI(one/vzero); /* -integer */
275 1.1 christos nadj = logl(pi/fabsl(t*x));
276 1.1 christos if(t<zero) *signgamp = -1;
277 1.1 christos x = -x;
278 1.1 christos }
279 1.1 christos
280 1.1 christos /* purge 1 and 2 */
281 1.1 christos if((ix==0x3fff || ix==0x4000) && lx==0x8000000000000000ULL) r = 0;
282 1.1 christos /* for x < 2.0 */
283 1.1 christos else if(ix<0x4000) {
284 1.1 christos /*
285 1.1 christos * XXX Supposedly, one can use the following information to replace the
286 1.1 christos * XXX FP rational expressions. A similar approach is appropriate
287 1.1 christos * XXX for ld128, but one (may need?) needs to consider llx, too.
288 1.1 christos *
289 1.1 christos * 8.9999961853027344e-01 3ffe e666600000000000
290 1.1 christos * 7.3159980773925781e-01 3ffe bb4a200000000000
291 1.1 christos * 2.3163998126983643e-01 3ffc ed33080000000000
292 1.1 christos * 1.7316312789916992e+00 3fff dda6180000000000
293 1.1 christos * 1.2316322326660156e+00 3fff 9da6200000000000
294 1.1 christos */
295 1.1 christos if(x<8.9999961853027344e-01) {
296 1.1 christos r = -logl(x);
297 1.1 christos if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
298 1.1 christos else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
299 1.1 christos else {y = x; i=2;}
300 1.1 christos } else {
301 1.1 christos r = 0;
302 1.1 christos if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
303 1.1 christos else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
304 1.1 christos else {y=x-1;i=2;}
305 1.1 christos }
306 1.1 christos switch(i) {
307 1.1 christos case 0:
308 1.1 christos z = y*y;
309 1.1 christos p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*a12)))));
310 1.1 christos p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*a13))))));
311 1.1 christos p = y*p1+p2;
312 1.1 christos r += p-y/2; break;
313 1.1 christos case 1:
314 1.1 christos p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
315 1.1 christos y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
316 1.1 christos y*(t17+y*t18))))))))))))))));
317 1.1 christos r += tf + p; break;
318 1.1 christos case 2:
319 1.1 christos p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*u6))))));
320 1.1 christos p2 = 1+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*v6)))));
321 1.1 christos r += p1/p2-y/2;
322 1.1 christos }
323 1.1 christos }
324 1.1 christos /* x < 8.0 */
325 1.1 christos else if(ix<0x4002) {
326 1.1 christos i = x;
327 1.1 christos y = x-i;
328 1.1 christos p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
329 1.1 christos q = 1+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*r7))))));
330 1.1 christos r = y/2+p/q;
331 1.1 christos z = 1; /* lgamma(1+s) = log(s) + lgamma(s) */
332 1.1 christos switch(i) {
333 1.1 christos case 7: z *= (y+6); /* FALLTHRU */
334 1.1 christos case 6: z *= (y+5); /* FALLTHRU */
335 1.1 christos case 5: z *= (y+4); /* FALLTHRU */
336 1.1 christos case 4: z *= (y+3); /* FALLTHRU */
337 1.1 christos case 3: z *= (y+2); /* FALLTHRU */
338 1.1 christos r += logl(z); break;
339 1.1 christos }
340 1.1 christos /* 8.0 <= x < 2**(p+3) */
341 1.1 christos } else if (ix<0x3fff+67) {
342 1.1 christos t = logl(x);
343 1.1 christos z = one/x;
344 1.1 christos y = z*z;
345 1.1 christos w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*w8)))))));
346 1.1 christos r = (x-half)*(t-one)+w;
347 1.1 christos /* 2**(p+3) <= x <= inf */
348 1.1 christos } else
349 1.1 christos r = x*(logl(x)-1);
350 1.1 christos if(hx&0x8000) r = nadj - r;
351 1.1 christos RETURNI(r);
352 1.1 christos }
353