(root)/
glibc-2.38/
sysdeps/
ieee754/
ldbl-96/
e_jnl.c
       1  /*
       2   * ====================================================
       3   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       4   *
       5   * Developed at SunPro, a Sun Microsystems, Inc. business.
       6   * Permission to use, copy, modify, and distribute this
       7   * software is freely granted, provided that this notice
       8   * is preserved.
       9   * ====================================================
      10   */
      11  
      12  /* Modifications for long double are
      13    Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
      14    and are incorporated herein by permission of the author.  The author
      15    reserves the right to distribute this material elsewhere under different
      16    copying permissions.  These modifications are distributed here under
      17    the following terms:
      18  
      19      This library is free software; you can redistribute it and/or
      20      modify it under the terms of the GNU Lesser General Public
      21      License as published by the Free Software Foundation; either
      22      version 2.1 of the License, or (at your option) any later version.
      23  
      24      This library is distributed in the hope that it will be useful,
      25      but WITHOUT ANY WARRANTY; without even the implied warranty of
      26      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      27      Lesser General Public License for more details.
      28  
      29      You should have received a copy of the GNU Lesser General Public
      30      License along with this library; if not, see
      31      <https://www.gnu.org/licenses/>.  */
      32  
      33  /*
      34   * __ieee754_jn(n, x), __ieee754_yn(n, x)
      35   * floating point Bessel's function of the 1st and 2nd kind
      36   * of order n
      37   *
      38   * Special cases:
      39   *	y0(0)=y1(0)=yn(n,0) = -inf with overflow signal;
      40   *	y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
      41   * Note 2. About jn(n,x), yn(n,x)
      42   *	For n=0, j0(x) is called,
      43   *	for n=1, j1(x) is called,
      44   *	for n<x, forward recursion us used starting
      45   *	from values of j0(x) and j1(x).
      46   *	for n>x, a continued fraction approximation to
      47   *	j(n,x)/j(n-1,x) is evaluated and then backward
      48   *	recursion is used starting from a supposed value
      49   *	for j(n,x). The resulting value of j(0,x) is
      50   *	compared with the actual value to correct the
      51   *	supposed value of j(n,x).
      52   *
      53   *	yn(n,x) is similar in all respects, except
      54   *	that forward recursion is used for all
      55   *	values of n>1.
      56   *
      57   */
      58  
      59  #include <errno.h>
      60  #include <float.h>
      61  #include <math.h>
      62  #include <math_private.h>
      63  #include <fenv_private.h>
      64  #include <math-underflow.h>
      65  #include <libm-alias-finite.h>
      66  
      67  static const long double
      68    invsqrtpi = 5.64189583547756286948079e-1L, two = 2.0e0L, one = 1.0e0L;
      69  
      70  static const long double zero = 0.0L;
      71  
      72  long double
      73  __ieee754_jnl (int n, long double x)
      74  {
      75    uint32_t se, i0, i1;
      76    int32_t i, ix, sgn;
      77    long double a, b, temp, di, ret;
      78    long double z, w;
      79  
      80    /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
      81     * Thus, J(-n,x) = J(n,-x)
      82     */
      83  
      84    GET_LDOUBLE_WORDS (se, i0, i1, x);
      85    ix = se & 0x7fff;
      86  
      87    /* if J(n,NaN) is NaN */
      88    if (__glibc_unlikely ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0)))
      89      return x + x;
      90    if (n < 0)
      91      {
      92        n = -n;
      93        x = -x;
      94        se ^= 0x8000;
      95      }
      96    if (n == 0)
      97      return (__ieee754_j0l (x));
      98    if (n == 1)
      99      return (__ieee754_j1l (x));
     100    sgn = (n & 1) & (se >> 15);	/* even n -- 0, odd n -- sign(x) */
     101    x = fabsl (x);
     102    {
     103      SET_RESTORE_ROUNDL (FE_TONEAREST);
     104      if (__glibc_unlikely ((ix | i0 | i1) == 0 || ix >= 0x7fff))
     105        /* if x is 0 or inf */
     106        return sgn == 1 ? -zero : zero;
     107      else if ((long double) n <= x)
     108        {
     109  	/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
     110  	if (ix >= 0x412D)
     111  	  {			/* x > 2**302 */
     112  
     113  	    /* ??? This might be a futile gesture.
     114  	       If x exceeds X_TLOSS anyway, the wrapper function
     115  	       will set the result to zero. */
     116  
     117  	    /* (x >> n**2)
     118  	     *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
     119  	     *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
     120  	     *      Let s=sin(x), c=cos(x),
     121  	     *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
     122  	     *
     123  	     *             n    sin(xn)*sqt2    cos(xn)*sqt2
     124  	     *          ----------------------------------
     125  	     *             0     s-c             c+s
     126  	     *             1    -s-c            -c+s
     127  	     *             2    -s+c            -c-s
     128  	     *             3     s+c             c-s
     129  	     */
     130  	    long double s;
     131  	    long double c;
     132  	    __sincosl (x, &s, &c);
     133  	    switch (n & 3)
     134  	      {
     135  	      case 0:
     136  		temp = c + s;
     137  		break;
     138  	      case 1:
     139  		temp = -c + s;
     140  		break;
     141  	      case 2:
     142  		temp = -c - s;
     143  		break;
     144  	      case 3:
     145  		temp = c - s;
     146  		break;
     147  	      default:
     148  		__builtin_unreachable ();
     149  	      }
     150  	    b = invsqrtpi * temp / sqrtl (x);
     151  	  }
     152  	else
     153  	  {
     154  	    a = __ieee754_j0l (x);
     155  	    b = __ieee754_j1l (x);
     156  	    for (i = 1; i < n; i++)
     157  	      {
     158  		temp = b;
     159  		b = b * ((long double) (i + i) / x) - a;	/* avoid underflow */
     160  		a = temp;
     161  	      }
     162  	  }
     163        }
     164      else
     165        {
     166  	if (ix < 0x3fde)
     167  	  {			/* x < 2**-33 */
     168  	    /* x is tiny, return the first Taylor expansion of J(n,x)
     169  	     * J(n,x) = 1/n!*(x/2)^n  - ...
     170  	     */
     171  	    if (n >= 400)		/* underflow, result < 10^-4952 */
     172  	      b = zero;
     173  	    else
     174  	      {
     175  		temp = x * 0.5;
     176  		b = temp;
     177  		for (a = one, i = 2; i <= n; i++)
     178  		  {
     179  		    a *= (long double) i;	/* a = n! */
     180  		    b *= temp;	/* b = (x/2)^n */
     181  		  }
     182  		b = b / a;
     183  	      }
     184  	  }
     185  	else
     186  	  {
     187  	    /* use backward recurrence */
     188  	    /*                      x      x^2      x^2
     189  	     *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
     190  	     *                      2n  - 2(n+1) - 2(n+2)
     191  	     *
     192  	     *                      1      1        1
     193  	     *  (for large x)   =  ----  ------   ------   .....
     194  	     *                      2n   2(n+1)   2(n+2)
     195  	     *                      -- - ------ - ------ -
     196  	     *                       x     x         x
     197  	     *
     198  	     * Let w = 2n/x and h=2/x, then the above quotient
     199  	     * is equal to the continued fraction:
     200  	     *                  1
     201  	     *      = -----------------------
     202  	     *                     1
     203  	     *         w - -----------------
     204  	     *                        1
     205  	     *              w+h - ---------
     206  	     *                     w+2h - ...
     207  	     *
     208  	     * To determine how many terms needed, let
     209  	     * Q(0) = w, Q(1) = w(w+h) - 1,
     210  	     * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
     211  	     * When Q(k) > 1e4      good for single
     212  	     * When Q(k) > 1e9      good for double
     213  	     * When Q(k) > 1e17     good for quadruple
     214  	     */
     215  	    /* determine k */
     216  	    long double t, v;
     217  	    long double q0, q1, h, tmp;
     218  	    int32_t k, m;
     219  	    w = (n + n) / (long double) x;
     220  	    h = 2.0L / (long double) x;
     221  	    q0 = w;
     222  	    z = w + h;
     223  	    q1 = w * z - 1.0L;
     224  	    k = 1;
     225  	    while (q1 < 1.0e11L)
     226  	      {
     227  		k += 1;
     228  		z += h;
     229  		tmp = z * q1 - q0;
     230  		q0 = q1;
     231  		q1 = tmp;
     232  	      }
     233  	    m = n + n;
     234  	    for (t = zero, i = 2 * (n + k); i >= m; i -= 2)
     235  	      t = one / (i / x - t);
     236  	    a = t;
     237  	    b = one;
     238  	    /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
     239  	     *  Hence, if n*(log(2n/x)) > ...
     240  	     *  single 8.8722839355e+01
     241  	     *  double 7.09782712893383973096e+02
     242  	     *  long double 1.1356523406294143949491931077970765006170e+04
     243  	     *  then recurrent value may overflow and the result is
     244  	     *  likely underflow to zero
     245  	     */
     246  	    tmp = n;
     247  	    v = two / x;
     248  	    tmp = tmp * __ieee754_logl (fabsl (v * tmp));
     249  
     250  	    if (tmp < 1.1356523406294143949491931077970765006170e+04L)
     251  	      {
     252  		for (i = n - 1, di = (long double) (i + i); i > 0; i--)
     253  		  {
     254  		    temp = b;
     255  		    b *= di;
     256  		    b = b / x - a;
     257  		    a = temp;
     258  		    di -= two;
     259  		  }
     260  	      }
     261  	    else
     262  	      {
     263  		for (i = n - 1, di = (long double) (i + i); i > 0; i--)
     264  		  {
     265  		    temp = b;
     266  		    b *= di;
     267  		    b = b / x - a;
     268  		    a = temp;
     269  		    di -= two;
     270  		    /* scale b to avoid spurious overflow */
     271  		    if (b > 1e100L)
     272  		      {
     273  			a /= b;
     274  			t /= b;
     275  			b = one;
     276  		      }
     277  		  }
     278  	      }
     279  	    /* j0() and j1() suffer enormous loss of precision at and
     280  	     * near zero; however, we know that their zero points never
     281  	     * coincide, so just choose the one further away from zero.
     282  	     */
     283  	    z = __ieee754_j0l (x);
     284  	    w = __ieee754_j1l (x);
     285  	    if (fabsl (z) >= fabsl (w))
     286  	      b = (t * z / b);
     287  	    else
     288  	      b = (t * w / a);
     289  	  }
     290        }
     291      if (sgn == 1)
     292        ret = -b;
     293      else
     294        ret = b;
     295    }
     296    if (ret == 0)
     297      {
     298        ret = copysignl (LDBL_MIN, ret) * LDBL_MIN;
     299        __set_errno (ERANGE);
     300      }
     301    else
     302      math_check_force_underflow (ret);
     303    return ret;
     304  }
     305  libm_alias_finite (__ieee754_jnl, __jnl)
     306  
     307  long double
     308  __ieee754_ynl (int n, long double x)
     309  {
     310    uint32_t se, i0, i1;
     311    int32_t i, ix;
     312    int32_t sign;
     313    long double a, b, temp, ret;
     314  
     315  
     316    GET_LDOUBLE_WORDS (se, i0, i1, x);
     317    ix = se & 0x7fff;
     318    /* if Y(n,NaN) is NaN */
     319    if (__builtin_expect ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0), 0))
     320      return x + x;
     321    if (__builtin_expect ((ix | i0 | i1) == 0, 0))
     322      /* -inf or inf and divide-by-zero exception.  */
     323      return ((n < 0 && (n & 1) != 0) ? 1.0L : -1.0L) / 0.0L;
     324    if (__builtin_expect (se & 0x8000, 0))
     325      return zero / (zero * x);
     326    sign = 1;
     327    if (n < 0)
     328      {
     329        n = -n;
     330        sign = 1 - ((n & 1) << 1);
     331      }
     332    if (n == 0)
     333      return (__ieee754_y0l (x));
     334    {
     335      SET_RESTORE_ROUNDL (FE_TONEAREST);
     336      if (n == 1)
     337        {
     338  	ret = sign * __ieee754_y1l (x);
     339  	goto out;
     340        }
     341      if (__glibc_unlikely (ix == 0x7fff))
     342        return zero;
     343      if (ix >= 0x412D)
     344        {				/* x > 2**302 */
     345  
     346  	/* ??? See comment above on the possible futility of this.  */
     347  
     348  	/* (x >> n**2)
     349  	 *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
     350  	 *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
     351  	 *      Let s=sin(x), c=cos(x),
     352  	 *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
     353  	 *
     354  	 *             n    sin(xn)*sqt2    cos(xn)*sqt2
     355  	 *          ----------------------------------
     356  	 *             0     s-c             c+s
     357  	 *             1    -s-c            -c+s
     358  	 *             2    -s+c            -c-s
     359  	 *             3     s+c             c-s
     360  	 */
     361  	long double s;
     362  	long double c;
     363  	__sincosl (x, &s, &c);
     364  	switch (n & 3)
     365  	  {
     366  	  case 0:
     367  	    temp = s - c;
     368  	    break;
     369  	  case 1:
     370  	    temp = -s - c;
     371  	    break;
     372  	  case 2:
     373  	    temp = -s + c;
     374  	    break;
     375  	  case 3:
     376  	    temp = s + c;
     377  	    break;
     378  	  default:
     379  	    __builtin_unreachable ();
     380  	  }
     381  	b = invsqrtpi * temp / sqrtl (x);
     382        }
     383      else
     384        {
     385  	a = __ieee754_y0l (x);
     386  	b = __ieee754_y1l (x);
     387  	/* quit if b is -inf */
     388  	GET_LDOUBLE_WORDS (se, i0, i1, b);
     389  	/* Use 0xffffffff since GET_LDOUBLE_WORDS sign-extends SE.  */
     390  	for (i = 1; i < n && se != 0xffffffff; i++)
     391  	  {
     392  	    temp = b;
     393  	    b = ((long double) (i + i) / x) * b - a;
     394  	    GET_LDOUBLE_WORDS (se, i0, i1, b);
     395  	    a = temp;
     396  	  }
     397        }
     398      /* If B is +-Inf, set up errno accordingly.  */
     399      if (! isfinite (b))
     400        __set_errno (ERANGE);
     401      if (sign > 0)
     402        ret = b;
     403      else
     404        ret = -b;
     405    }
     406   out:
     407    if (isinf (ret))
     408      ret = copysignl (LDBL_MAX, ret) * LDBL_MAX;
     409    return ret;
     410  }
     411  libm_alias_finite (__ieee754_ynl, __ynl)