1d59437c0Smrg /* mpfr_y0, mpfr_y1, mpfr_yn -- Bessel functions of 2nd kind, integer order.
2ba125506Smrg https://pubs.opengroup.org/onlinepubs/9699919799/functions/y0.html
3d59437c0Smrg
4ba125506Smrg Copyright 2007-2023 Free Software Foundation, Inc.
5efdec83bSmrg Contributed by the AriC and Caramba projects, INRIA.
6d59437c0Smrg
7d59437c0Smrg This file is part of the GNU MPFR Library.
8d59437c0Smrg
9d59437c0Smrg The GNU MPFR Library is free software; you can redistribute it and/or modify
10d59437c0Smrg it under the terms of the GNU Lesser General Public License as published by
11d59437c0Smrg the Free Software Foundation; either version 3 of the License, or (at your
12d59437c0Smrg option) any later version.
13d59437c0Smrg
14d59437c0Smrg The GNU MPFR Library is distributed in the hope that it will be useful, but
15d59437c0Smrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16d59437c0Smrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17d59437c0Smrg License for more details.
18d59437c0Smrg
19d59437c0Smrg You should have received a copy of the GNU Lesser General Public License
20d59437c0Smrg along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
212ba2404bSmrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22d59437c0Smrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23d59437c0Smrg
24d59437c0Smrg #define MPFR_NEED_LONGLONG_H
25d59437c0Smrg #include "mpfr-impl.h"
26d59437c0Smrg
27d59437c0Smrg static int mpfr_yn_asympt (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t);
28d59437c0Smrg
29d59437c0Smrg int
mpfr_y0(mpfr_ptr res,mpfr_srcptr z,mpfr_rnd_t r)30d59437c0Smrg mpfr_y0 (mpfr_ptr res, mpfr_srcptr z, mpfr_rnd_t r)
31d59437c0Smrg {
32d59437c0Smrg return mpfr_yn (res, 0, z, r);
33d59437c0Smrg }
34d59437c0Smrg
35d59437c0Smrg int
mpfr_y1(mpfr_ptr res,mpfr_srcptr z,mpfr_rnd_t r)36d59437c0Smrg mpfr_y1 (mpfr_ptr res, mpfr_srcptr z, mpfr_rnd_t r)
37d59437c0Smrg {
38d59437c0Smrg return mpfr_yn (res, 1, z, r);
39d59437c0Smrg }
40d59437c0Smrg
41d59437c0Smrg /* compute in s an approximation of S1 = sum((n-k)!/k!*y^k,k=0..n)
42d59437c0Smrg return e >= 0 the exponent difference between the maximal value of |s|
43d59437c0Smrg during the for loop and the final value of |s|.
44d59437c0Smrg */
45d59437c0Smrg static mpfr_exp_t
mpfr_yn_s1(mpfr_ptr s,mpfr_srcptr y,unsigned long n)46d59437c0Smrg mpfr_yn_s1 (mpfr_ptr s, mpfr_srcptr y, unsigned long n)
47d59437c0Smrg {
48d59437c0Smrg unsigned long k;
49d59437c0Smrg mpz_t f;
50d59437c0Smrg mpfr_exp_t e, emax;
51d59437c0Smrg
52d59437c0Smrg mpz_init_set_ui (f, 1);
53d59437c0Smrg /* we compute n!*S1 = sum(a[k]*y^k,k=0..n) where a[k] = n!*(n-k)!/k!,
54d59437c0Smrg a[0] = (n!)^2, a[1] = n!*(n-1)!, ..., a[n-1] = n, a[n] = 1 */
55d59437c0Smrg mpfr_set_ui (s, 1, MPFR_RNDN); /* a[n] */
56d59437c0Smrg emax = MPFR_EXP(s);
57d59437c0Smrg for (k = n; k-- > 0;)
58d59437c0Smrg {
59d59437c0Smrg /* a[k]/a[k+1] = (n-k)!/k!/(n-(k+1))!*(k+1)! = (k+1)*(n-k) */
60d59437c0Smrg mpfr_mul (s, s, y, MPFR_RNDN);
61d59437c0Smrg mpz_mul_ui (f, f, n - k);
62d59437c0Smrg mpz_mul_ui (f, f, k + 1);
63d59437c0Smrg /* invariant: f = a[k] */
64d59437c0Smrg mpfr_add_z (s, s, f, MPFR_RNDN);
65d59437c0Smrg e = MPFR_EXP(s);
66d59437c0Smrg if (e > emax)
67d59437c0Smrg emax = e;
68d59437c0Smrg }
69d59437c0Smrg /* now we have f = (n!)^2 */
70d59437c0Smrg mpz_sqrt (f, f);
71d59437c0Smrg mpfr_div_z (s, s, f, MPFR_RNDN);
72d59437c0Smrg mpz_clear (f);
73d59437c0Smrg return emax - MPFR_EXP(s);
74d59437c0Smrg }
75d59437c0Smrg
76d59437c0Smrg /* compute in s an approximation of
77d59437c0Smrg S3 = c*sum((h(k)+h(n+k))*y^k/k!/(n+k)!,k=0..infinity)
78d59437c0Smrg where h(k) = 1 + 1/2 + ... + 1/k
79d59437c0Smrg k=0: h(n)
80d59437c0Smrg k=1: 1+h(n+1)
81d59437c0Smrg k=2: 3/2+h(n+2)
82d59437c0Smrg Returns e such that the error is bounded by 2^e ulp(s).
83d59437c0Smrg */
84d59437c0Smrg static mpfr_exp_t
mpfr_yn_s3(mpfr_ptr s,mpfr_srcptr y,mpfr_srcptr c,unsigned long n)85d59437c0Smrg mpfr_yn_s3 (mpfr_ptr s, mpfr_srcptr y, mpfr_srcptr c, unsigned long n)
86d59437c0Smrg {
87d59437c0Smrg unsigned long k, zz;
88d59437c0Smrg mpfr_t t, u;
89d59437c0Smrg mpz_t p, q; /* p/q will store h(k)+h(n+k) */
90d59437c0Smrg mpfr_exp_t exps, expU;
91d59437c0Smrg
92d59437c0Smrg zz = mpfr_get_ui (y, MPFR_RNDU); /* y = z^2/4 */
93d59437c0Smrg MPFR_ASSERTN (zz < ULONG_MAX - 2);
94d59437c0Smrg zz += 2; /* z^2 <= 2^zz */
95d59437c0Smrg mpz_init_set_ui (p, 0);
96d59437c0Smrg mpz_init_set_ui (q, 1);
97d59437c0Smrg /* initialize p/q to h(n) */
98d59437c0Smrg for (k = 1; k <= n; k++)
99d59437c0Smrg {
100d59437c0Smrg /* p/q + 1/k = (k*p+q)/(q*k) */
101d59437c0Smrg mpz_mul_ui (p, p, k);
102d59437c0Smrg mpz_add (p, p, q);
103d59437c0Smrg mpz_mul_ui (q, q, k);
104d59437c0Smrg }
105d59437c0Smrg mpfr_init2 (t, MPFR_PREC(s));
106d59437c0Smrg mpfr_init2 (u, MPFR_PREC(s));
107d59437c0Smrg mpfr_fac_ui (t, n, MPFR_RNDN);
108d59437c0Smrg mpfr_div (t, c, t, MPFR_RNDN); /* c/n! */
109d59437c0Smrg mpfr_mul_z (u, t, p, MPFR_RNDN);
110d59437c0Smrg mpfr_div_z (s, u, q, MPFR_RNDN);
111d59437c0Smrg exps = MPFR_EXP (s);
112d59437c0Smrg expU = exps;
113d59437c0Smrg for (k = 1; ;k ++)
114d59437c0Smrg {
115d59437c0Smrg /* update t */
116d59437c0Smrg mpfr_mul (t, t, y, MPFR_RNDN);
117d59437c0Smrg mpfr_div_ui (t, t, k, MPFR_RNDN);
118d59437c0Smrg mpfr_div_ui (t, t, n + k, MPFR_RNDN);
119d59437c0Smrg /* update p/q:
120d59437c0Smrg p/q + 1/k + 1/(n+k) = [p*k*(n+k) + q*(n+k) + q*k]/(q*k*(n+k)) */
121d59437c0Smrg mpz_mul_ui (p, p, k);
122d59437c0Smrg mpz_mul_ui (p, p, n + k);
123d59437c0Smrg mpz_addmul_ui (p, q, n + 2 * k);
124d59437c0Smrg mpz_mul_ui (q, q, k);
125d59437c0Smrg mpz_mul_ui (q, q, n + k);
126d59437c0Smrg mpfr_mul_z (u, t, p, MPFR_RNDN);
127d59437c0Smrg mpfr_div_z (u, u, q, MPFR_RNDN);
128d59437c0Smrg exps = MPFR_EXP (u);
129d59437c0Smrg if (exps > expU)
130d59437c0Smrg expU = exps;
131d59437c0Smrg mpfr_add (s, s, u, MPFR_RNDN);
132d59437c0Smrg exps = MPFR_EXP (s);
133d59437c0Smrg if (exps > expU)
134d59437c0Smrg expU = exps;
135d59437c0Smrg if (MPFR_EXP (u) + (mpfr_exp_t) MPFR_PREC (u) < MPFR_EXP (s) &&
136d59437c0Smrg zz / (2 * k) < k + n)
137d59437c0Smrg break;
138d59437c0Smrg }
139d59437c0Smrg mpfr_clear (t);
140d59437c0Smrg mpfr_clear (u);
141d59437c0Smrg mpz_clear (p);
142d59437c0Smrg mpz_clear (q);
143d59437c0Smrg exps = expU - MPFR_EXP (s);
144d59437c0Smrg /* the error is bounded by (6k^2+33/2k+11) 2^exps ulps
145d59437c0Smrg <= 8*(k+2)^2 2^exps ulps */
146d59437c0Smrg return 3 + 2 * MPFR_INT_CEIL_LOG2(k + 2) + exps;
147d59437c0Smrg }
148d59437c0Smrg
149d59437c0Smrg int
mpfr_yn(mpfr_ptr res,long n,mpfr_srcptr z,mpfr_rnd_t r)150d59437c0Smrg mpfr_yn (mpfr_ptr res, long n, mpfr_srcptr z, mpfr_rnd_t r)
151d59437c0Smrg {
152d59437c0Smrg int inex;
153d59437c0Smrg unsigned long absn;
154d59437c0Smrg MPFR_SAVE_EXPO_DECL (expo);
155d59437c0Smrg
156d59437c0Smrg MPFR_LOG_FUNC
157*ec6772edSmrg (("n=%ld x[%Pd]=%.*Rg rnd=%d", n, mpfr_get_prec (z), mpfr_log_prec, z, r),
158*ec6772edSmrg ("y[%Pd]=%.*Rg inexact=%d", mpfr_get_prec (res), mpfr_log_prec, res, inex));
159d59437c0Smrg
160d59437c0Smrg absn = SAFE_ABS (unsigned long, n);
161d59437c0Smrg
162d59437c0Smrg if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (z)))
163d59437c0Smrg {
164d59437c0Smrg if (MPFR_IS_NAN (z))
165d59437c0Smrg {
166d59437c0Smrg MPFR_SET_NAN (res); /* y(n,NaN) = NaN */
167d59437c0Smrg MPFR_RET_NAN;
168d59437c0Smrg }
169d59437c0Smrg /* y(n,z) tends to zero when z goes to +Inf, oscillating around
170d59437c0Smrg 0. We choose to return +0 in that case. */
171d59437c0Smrg else if (MPFR_IS_INF (z))
172d59437c0Smrg {
173299c6f0cSmrg if (MPFR_IS_POS (z))
174d59437c0Smrg return mpfr_set_ui (res, 0, r);
175d59437c0Smrg else /* y(n,-Inf) = NaN */
176d59437c0Smrg {
177d59437c0Smrg MPFR_SET_NAN (res);
178d59437c0Smrg MPFR_RET_NAN;
179d59437c0Smrg }
180d59437c0Smrg }
181d59437c0Smrg else /* y(n,z) tends to -Inf for n >= 0 or n even, to +Inf otherwise,
182d59437c0Smrg when z goes to zero */
183d59437c0Smrg {
184d59437c0Smrg MPFR_SET_INF(res);
185d59437c0Smrg if (n >= 0 || ((unsigned long) n & 1) == 0)
186d59437c0Smrg MPFR_SET_NEG(res);
187d59437c0Smrg else
188d59437c0Smrg MPFR_SET_POS(res);
189299c6f0cSmrg MPFR_SET_DIVBY0 ();
190d59437c0Smrg MPFR_RET(0);
191d59437c0Smrg }
192d59437c0Smrg }
193d59437c0Smrg
194d59437c0Smrg /* for z < 0, y(n,z) is imaginary except when j(n,|z|) = 0, which we
195d59437c0Smrg assume does not happen for a rational z. */
196299c6f0cSmrg if (MPFR_IS_NEG (z))
197d59437c0Smrg {
198d59437c0Smrg MPFR_SET_NAN (res);
199d59437c0Smrg MPFR_RET_NAN;
200d59437c0Smrg }
201d59437c0Smrg
202d59437c0Smrg /* now z is not singular, and z > 0 */
203d59437c0Smrg
204d59437c0Smrg MPFR_SAVE_EXPO_MARK (expo);
205d59437c0Smrg
206d59437c0Smrg /* Deal with tiny arguments. We have:
207d59437c0Smrg y0(z) = 2 log(z)/Pi + 2 (euler - log(2))/Pi + O(log(z)*z^2), more
208d59437c0Smrg precisely for 0 <= z <= 1/2, with g(z) = 2/Pi + 2(euler-log(2))/Pi/log(z),
209d59437c0Smrg g(z) - 0.41*z^2 < y0(z)/log(z) < g(z)
210d59437c0Smrg thus since log(z) is negative:
211d59437c0Smrg g(z)*log(z) < y0(z) < (g(z) - z^2/2)*log(z)
212d59437c0Smrg and since |g(z)| >= 0.63 for 0 <= z <= 1/2, the relative error on
213d59437c0Smrg y0(z)/log(z) is bounded by 0.41*z^2/0.63 <= 0.66*z^2.
214d59437c0Smrg Note: we use both the main term in log(z) and the constant term, because
215d59437c0Smrg otherwise the relative error would be only in 1/log(|log(z)|).
216d59437c0Smrg */
217d59437c0Smrg if (n == 0 && MPFR_EXP(z) < - (mpfr_exp_t) (MPFR_PREC(res) / 2))
218d59437c0Smrg {
219d59437c0Smrg mpfr_t l, h, t, logz;
220d59437c0Smrg mpfr_prec_t prec;
221d59437c0Smrg int ok, inex2;
222d59437c0Smrg
223d59437c0Smrg prec = MPFR_PREC(res) + 10;
224d59437c0Smrg mpfr_init2 (l, prec);
225d59437c0Smrg mpfr_init2 (h, prec);
226d59437c0Smrg mpfr_init2 (t, prec);
227d59437c0Smrg mpfr_init2 (logz, prec);
228d59437c0Smrg /* first enclose log(z) + euler - log(2) = log(z/2) + euler */
229d59437c0Smrg mpfr_log (logz, z, MPFR_RNDD); /* lower bound of log(z) */
230d59437c0Smrg mpfr_set (h, logz, MPFR_RNDU); /* exact */
231d59437c0Smrg mpfr_nextabove (h); /* upper bound of log(z) */
232d59437c0Smrg mpfr_const_euler (t, MPFR_RNDD); /* lower bound of euler */
233d59437c0Smrg mpfr_add (l, logz, t, MPFR_RNDD); /* lower bound of log(z) + euler */
234d59437c0Smrg mpfr_nextabove (t); /* upper bound of euler */
235d59437c0Smrg mpfr_add (h, h, t, MPFR_RNDU); /* upper bound of log(z) + euler */
236d59437c0Smrg mpfr_const_log2 (t, MPFR_RNDU); /* upper bound of log(2) */
237d59437c0Smrg mpfr_sub (l, l, t, MPFR_RNDD); /* lower bound of log(z/2) + euler */
238d59437c0Smrg mpfr_nextbelow (t); /* lower bound of log(2) */
239d59437c0Smrg mpfr_sub (h, h, t, MPFR_RNDU); /* upper bound of log(z/2) + euler */
240d59437c0Smrg mpfr_const_pi (t, MPFR_RNDU); /* upper bound of Pi */
241d59437c0Smrg mpfr_div (l, l, t, MPFR_RNDD); /* lower bound of (log(z/2)+euler)/Pi */
242d59437c0Smrg mpfr_nextbelow (t); /* lower bound of Pi */
243d59437c0Smrg mpfr_div (h, h, t, MPFR_RNDD); /* upper bound of (log(z/2)+euler)/Pi */
244d59437c0Smrg mpfr_mul_2ui (l, l, 1, MPFR_RNDD); /* lower bound on g(z)*log(z) */
245d59437c0Smrg mpfr_mul_2ui (h, h, 1, MPFR_RNDU); /* upper bound on g(z)*log(z) */
246d59437c0Smrg /* we now have l <= g(z)*log(z) <= h, and we need to add -z^2/2*log(z)
247d59437c0Smrg to h */
2482ba2404bSmrg mpfr_sqr (t, z, MPFR_RNDU); /* upper bound on z^2 */
249d59437c0Smrg /* since logz is negative, a lower bound corresponds to an upper bound
250d59437c0Smrg for its absolute value */
251d59437c0Smrg mpfr_neg (t, t, MPFR_RNDD);
252d59437c0Smrg mpfr_div_2ui (t, t, 1, MPFR_RNDD);
253d59437c0Smrg mpfr_mul (t, t, logz, MPFR_RNDU); /* upper bound on z^2/2*log(z) */
254d59437c0Smrg mpfr_add (h, h, t, MPFR_RNDU);
255d59437c0Smrg inex = mpfr_prec_round (l, MPFR_PREC(res), r);
256d59437c0Smrg inex2 = mpfr_prec_round (h, MPFR_PREC(res), r);
257d59437c0Smrg /* we need h=l and inex=inex2 */
258d59437c0Smrg ok = (inex == inex2) && mpfr_equal_p (l, h);
259d59437c0Smrg if (ok)
260d59437c0Smrg mpfr_set (res, h, r); /* exact */
261d59437c0Smrg mpfr_clear (l);
262d59437c0Smrg mpfr_clear (h);
263d59437c0Smrg mpfr_clear (t);
264d59437c0Smrg mpfr_clear (logz);
265d59437c0Smrg if (ok)
266d59437c0Smrg goto end;
267d59437c0Smrg }
268d59437c0Smrg
269d59437c0Smrg /* small argument check for y1(z) = -2/Pi/z + O(log(z)):
270d59437c0Smrg for 0 <= z <= 1, |y1(z) + 2/Pi/z| <= 0.25 */
271d59437c0Smrg if (n == 1 && MPFR_EXP(z) + 1 < - (mpfr_exp_t) MPFR_PREC(res))
272d59437c0Smrg {
273d59437c0Smrg mpfr_t y;
274d59437c0Smrg mpfr_prec_t prec;
275d59437c0Smrg mpfr_exp_t err1;
276d59437c0Smrg int ok;
277d59437c0Smrg MPFR_BLOCK_DECL (flags);
278d59437c0Smrg
279d59437c0Smrg /* since 2/Pi > 0.5, and |y1(z)| >= |2/Pi/z|, if z <= 2^(-emax-1),
280d59437c0Smrg then |y1(z)| > 2^emax */
281d59437c0Smrg prec = MPFR_PREC(res) + 10;
282d59437c0Smrg mpfr_init2 (y, prec);
283d59437c0Smrg mpfr_const_pi (y, MPFR_RNDU); /* Pi*(1+u)^2, where here and below u
284d59437c0Smrg represents a quantity <= 1/2^prec */
285d59437c0Smrg mpfr_mul (y, y, z, MPFR_RNDU); /* Pi*z * (1+u)^4, upper bound */
286d59437c0Smrg MPFR_BLOCK (flags, mpfr_ui_div (y, 2, y, MPFR_RNDZ));
287d59437c0Smrg /* 2/Pi/z * (1+u)^6, lower bound, with possible overflow */
288d59437c0Smrg if (MPFR_OVERFLOW (flags))
289d59437c0Smrg {
290d59437c0Smrg mpfr_clear (y);
291d59437c0Smrg MPFR_SAVE_EXPO_FREE (expo);
292d59437c0Smrg return mpfr_overflow (res, r, -1);
293d59437c0Smrg }
294d59437c0Smrg mpfr_neg (y, y, MPFR_RNDN);
295d59437c0Smrg /* (1+u)^6 can be written 1+7u [for another value of u], thus the
296d59437c0Smrg error on 2/Pi/z is less than 7ulp(y). The truncation error is less
297d59437c0Smrg than 1/4, thus if ulp(y)>=1/4, the total error is less than 8ulp(y),
298d59437c0Smrg otherwise it is less than 1/4+7/8 <= 2. */
299d59437c0Smrg if (MPFR_EXP(y) + 2 >= MPFR_PREC(y)) /* ulp(y) >= 1/4 */
300d59437c0Smrg err1 = 3;
301d59437c0Smrg else /* ulp(y) <= 1/8 */
302d59437c0Smrg err1 = (mpfr_exp_t) MPFR_PREC(y) - MPFR_EXP(y) + 1;
303d59437c0Smrg ok = MPFR_CAN_ROUND (y, prec - err1, MPFR_PREC(res), r);
304d59437c0Smrg if (ok)
305d59437c0Smrg inex = mpfr_set (res, y, r);
306d59437c0Smrg mpfr_clear (y);
307d59437c0Smrg if (ok)
308d59437c0Smrg goto end;
309d59437c0Smrg }
310d59437c0Smrg
311d59437c0Smrg /* we can use the asymptotic expansion as soon as z > p log(2)/2,
312d59437c0Smrg but to get some margin we use it for z > p/2 */
313d59437c0Smrg if (mpfr_cmp_ui (z, MPFR_PREC(res) / 2 + 3) > 0)
314d59437c0Smrg {
315d59437c0Smrg inex = mpfr_yn_asympt (res, n, z, r);
316d59437c0Smrg if (inex != 0)
317d59437c0Smrg goto end;
318d59437c0Smrg }
319d59437c0Smrg
320d59437c0Smrg /* General case */
321d59437c0Smrg {
322d59437c0Smrg mpfr_prec_t prec;
323d59437c0Smrg mpfr_exp_t err1, err2, err3;
324d59437c0Smrg mpfr_t y, s1, s2, s3;
325d59437c0Smrg MPFR_ZIV_DECL (loop);
326d59437c0Smrg
327d59437c0Smrg prec = MPFR_PREC(res) + 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC (res)) + 13;
328ba125506Smrg
329ba125506Smrg mpfr_init2 (y, prec);
330ba125506Smrg mpfr_init2 (s1, prec);
331ba125506Smrg mpfr_init2 (s2, prec);
332ba125506Smrg mpfr_init2 (s3, prec);
333ba125506Smrg
334d59437c0Smrg MPFR_ZIV_INIT (loop, prec);
335d59437c0Smrg for (;;)
336d59437c0Smrg {
337d59437c0Smrg mpfr_set_prec (y, prec);
338d59437c0Smrg mpfr_set_prec (s1, prec);
339d59437c0Smrg mpfr_set_prec (s2, prec);
340d59437c0Smrg mpfr_set_prec (s3, prec);
341d59437c0Smrg
3422ba2404bSmrg mpfr_sqr (y, z, MPFR_RNDN);
343d59437c0Smrg mpfr_div_2ui (y, y, 2, MPFR_RNDN); /* z^2/4 */
344d59437c0Smrg
345d59437c0Smrg /* store (z/2)^n temporarily in s2 */
346d59437c0Smrg mpfr_pow_ui (s2, z, absn, MPFR_RNDN);
347d59437c0Smrg mpfr_div_2si (s2, s2, absn, MPFR_RNDN);
348d59437c0Smrg
349d59437c0Smrg /* compute S1 * (z/2)^(-n) */
350d59437c0Smrg if (n == 0)
351d59437c0Smrg {
352d59437c0Smrg mpfr_set_ui (s1, 0, MPFR_RNDN);
353d59437c0Smrg err1 = 0;
354d59437c0Smrg }
355d59437c0Smrg else
356d59437c0Smrg err1 = mpfr_yn_s1 (s1, y, absn - 1);
357d59437c0Smrg mpfr_div (s1, s1, s2, MPFR_RNDN); /* (z/2)^(-n) * S1 */
358d59437c0Smrg /* See algorithms.tex: the relative error on s1 is bounded by
359d59437c0Smrg (3n+3)*2^(e+1-prec). */
360d59437c0Smrg err1 = MPFR_INT_CEIL_LOG2 (3 * absn + 3) + err1 + 1;
361d59437c0Smrg /* rel_err(s1) <= 2^(err1-prec), thus err(s1) <= 2^err1 ulps */
362d59437c0Smrg
363d59437c0Smrg /* compute (z/2)^n * S3 */
364d59437c0Smrg mpfr_neg (y, y, MPFR_RNDN); /* -z^2/4 */
365d59437c0Smrg err3 = mpfr_yn_s3 (s3, y, s2, absn); /* (z/2)^n * S3 */
366d59437c0Smrg /* the error on s3 is bounded by 2^err3 ulps */
367d59437c0Smrg
368d59437c0Smrg /* add s1+s3 */
369d59437c0Smrg err1 += MPFR_EXP(s1);
370d59437c0Smrg mpfr_add (s1, s1, s3, MPFR_RNDN);
371d59437c0Smrg /* the error is bounded by 1/2 + 2^err1*2^(- EXP(s1))
372d59437c0Smrg + 2^err3*2^(EXP(s3) - EXP(s1)) */
373d59437c0Smrg err3 += MPFR_EXP(s3);
374d59437c0Smrg err1 = (err3 > err1) ? err3 + 1 : err1 + 1;
375d59437c0Smrg err1 -= MPFR_EXP(s1);
376d59437c0Smrg err1 = (err1 >= 0) ? err1 + 1 : 1;
377d59437c0Smrg /* now the error on s1 is bounded by 2^err1*ulp(s1) */
378d59437c0Smrg
379d59437c0Smrg /* compute S2 */
380d59437c0Smrg mpfr_div_2ui (s2, z, 1, MPFR_RNDN); /* z/2 */
381d59437c0Smrg mpfr_log (s2, s2, MPFR_RNDN); /* log(z/2) */
382d59437c0Smrg mpfr_const_euler (s3, MPFR_RNDN);
383d59437c0Smrg err2 = MPFR_EXP(s2) > MPFR_EXP(s3) ? MPFR_EXP(s2) : MPFR_EXP(s3);
384d59437c0Smrg mpfr_add (s2, s2, s3, MPFR_RNDN); /* log(z/2) + gamma */
385d59437c0Smrg err2 -= MPFR_EXP(s2);
386d59437c0Smrg mpfr_mul_2ui (s2, s2, 1, MPFR_RNDN); /* 2*(log(z/2) + gamma) */
387d59437c0Smrg mpfr_jn (s3, absn, z, MPFR_RNDN); /* Jn(z) */
388d59437c0Smrg mpfr_mul (s2, s2, s3, MPFR_RNDN); /* 2*(log(z/2) + gamma)*Jn(z) */
389d59437c0Smrg err2 += 4; /* the error on s2 is bounded by 2^err2 ulps, see
390d59437c0Smrg algorithms.tex */
391d59437c0Smrg
392d59437c0Smrg /* add all three sums */
393d59437c0Smrg err1 += MPFR_EXP(s1); /* the error on s1 is bounded by 2^err1 */
394d59437c0Smrg err2 += MPFR_EXP(s2); /* the error on s2 is bounded by 2^err2 */
395d59437c0Smrg mpfr_sub (s2, s2, s1, MPFR_RNDN); /* s2 - (s1+s3) */
396d59437c0Smrg err2 = (err1 > err2) ? err1 + 1 : err2 + 1;
397d59437c0Smrg err2 -= MPFR_EXP(s2);
398d59437c0Smrg err2 = (err2 >= 0) ? err2 + 1 : 1;
399d59437c0Smrg /* now the error on s2 is bounded by 2^err2*ulp(s2) */
400d59437c0Smrg mpfr_const_pi (y, MPFR_RNDN); /* error bounded by 1 ulp */
401d59437c0Smrg mpfr_div (s2, s2, y, MPFR_RNDN); /* error bounded by
402d59437c0Smrg 2^(err2+1)*ulp(s2) */
403d59437c0Smrg err2 ++;
404d59437c0Smrg
405d59437c0Smrg if (MPFR_LIKELY (MPFR_CAN_ROUND (s2, prec - err2, MPFR_PREC(res), r)))
406d59437c0Smrg break;
407d59437c0Smrg MPFR_ZIV_NEXT (loop, prec);
408d59437c0Smrg }
409d59437c0Smrg MPFR_ZIV_FREE (loop);
410d59437c0Smrg
411d59437c0Smrg /* Assume two's complement for the test n & 1 */
412d59437c0Smrg inex = mpfr_set4 (res, s2, r, n >= 0 || (n & 1) == 0 ?
413d59437c0Smrg MPFR_SIGN (s2) : - MPFR_SIGN (s2));
414d59437c0Smrg
415d59437c0Smrg mpfr_clear (y);
416d59437c0Smrg mpfr_clear (s1);
417d59437c0Smrg mpfr_clear (s2);
418d59437c0Smrg mpfr_clear (s3);
419d59437c0Smrg }
420d59437c0Smrg
421d59437c0Smrg end:
422d59437c0Smrg MPFR_SAVE_EXPO_FREE (expo);
423d59437c0Smrg return mpfr_check_range (res, inex, r);
424d59437c0Smrg }
425d59437c0Smrg
426d59437c0Smrg #define MPFR_YN
427d59437c0Smrg #include "jyn_asympt.c"
428