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