about summary refs log tree commit diff
path: root/sysdeps/ieee754/ldbl-96
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ieee754/ldbl-96')
-rw-r--r--sysdeps/ieee754/ldbl-96/e_jnl.c137
1 files changed, 74 insertions, 63 deletions
diff --git a/sysdeps/ieee754/ldbl-96/e_jnl.c b/sysdeps/ieee754/ldbl-96/e_jnl.c
index 11d097c271..95ff24201b 100644
--- a/sysdeps/ieee754/ldbl-96/e_jnl.c
+++ b/sysdeps/ieee754/ldbl-96/e_jnl.c
@@ -57,6 +57,7 @@
  */
 
 #include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -293,7 +294,7 @@ __ieee754_ynl (int n, long double x)
   u_int32_t se, i0, i1;
   int32_t i, ix;
   int32_t sign;
-  long double a, b, temp;
+  long double a, b, temp, ret;
 
 
   GET_LDOUBLE_WORDS (se, i0, i1, x);
@@ -314,69 +315,79 @@ __ieee754_ynl (int n, long double x)
     }
   if (n == 0)
     return (__ieee754_y0l (x));
-  if (n == 1)
-    return (sign * __ieee754_y1l (x));
-  if (__glibc_unlikely (ix == 0x7fff))
-    return zero;
-  if (ix >= 0x412D)
-    {				/* x > 2**302 */
+  {
+    SET_RESTORE_ROUNDL (FE_TONEAREST);
+    if (n == 1)
+      {
+	ret = sign * __ieee754_y1l (x);
+	goto out;
+      }
+    if (__glibc_unlikely (ix == 0x7fff))
+      return zero;
+    if (ix >= 0x412D)
+      {				/* x > 2**302 */
 
-      /* ??? See comment above on the possible futility of this.  */
+	/* ??? See comment above on the possible futility of this.  */
 
-      /* (x >> n**2)
-       *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
-       *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
-       *      Let s=sin(x), c=cos(x),
-       *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
-       *
-       *             n    sin(xn)*sqt2    cos(xn)*sqt2
-       *          ----------------------------------
-       *             0     s-c             c+s
-       *             1    -s-c            -c+s
-       *             2    -s+c            -c-s
-       *             3     s+c             c-s
-       */
-      long double s;
-      long double c;
-      __sincosl (x, &s, &c);
-      switch (n & 3)
-	{
-	case 0:
-	  temp = s - c;
-	  break;
-	case 1:
-	  temp = -s - c;
-	  break;
-	case 2:
-	  temp = -s + c;
-	  break;
-	case 3:
-	  temp = s + c;
-	  break;
-	}
-      b = invsqrtpi * temp / __ieee754_sqrtl (x);
-    }
-  else
-    {
-      a = __ieee754_y0l (x);
-      b = __ieee754_y1l (x);
-      /* quit if b is -inf */
-      GET_LDOUBLE_WORDS (se, i0, i1, b);
-      /* Use 0xffffffff since GET_LDOUBLE_WORDS sign-extends SE.  */
-      for (i = 1; i < n && se != 0xffffffff; i++)
-	{
-	  temp = b;
-	  b = ((long double) (i + i) / x) * b - a;
-	  GET_LDOUBLE_WORDS (se, i0, i1, b);
-	  a = temp;
-	}
-    }
-  /* If B is +-Inf, set up errno accordingly.  */
-  if (! __finitel (b))
-    __set_errno (ERANGE);
-  if (sign > 0)
-    return b;
-  else
-    return -b;
+	/* (x >> n**2)
+	 *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+	 *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+	 *      Let s=sin(x), c=cos(x),
+	 *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+	 *
+	 *             n    sin(xn)*sqt2    cos(xn)*sqt2
+	 *          ----------------------------------
+	 *             0     s-c             c+s
+	 *             1    -s-c            -c+s
+	 *             2    -s+c            -c-s
+	 *             3     s+c             c-s
+	 */
+	long double s;
+	long double c;
+	__sincosl (x, &s, &c);
+	switch (n & 3)
+	  {
+	  case 0:
+	    temp = s - c;
+	    break;
+	  case 1:
+	    temp = -s - c;
+	    break;
+	  case 2:
+	    temp = -s + c;
+	    break;
+	  case 3:
+	    temp = s + c;
+	    break;
+	  }
+	b = invsqrtpi * temp / __ieee754_sqrtl (x);
+      }
+    else
+      {
+	a = __ieee754_y0l (x);
+	b = __ieee754_y1l (x);
+	/* quit if b is -inf */
+	GET_LDOUBLE_WORDS (se, i0, i1, b);
+	/* Use 0xffffffff since GET_LDOUBLE_WORDS sign-extends SE.  */
+	for (i = 1; i < n && se != 0xffffffff; i++)
+	  {
+	    temp = b;
+	    b = ((long double) (i + i) / x) * b - a;
+	    GET_LDOUBLE_WORDS (se, i0, i1, b);
+	    a = temp;
+	  }
+      }
+    /* If B is +-Inf, set up errno accordingly.  */
+    if (! __finitel (b))
+      __set_errno (ERANGE);
+    if (sign > 0)
+      ret = b;
+    else
+      ret = -b;
+  }
+ out:
+  if (__isinfl (ret))
+    ret = __copysignl (LDBL_MAX, ret) * LDBL_MAX;
+  return ret;
 }
 strong_alias (__ieee754_ynl, __ynl_finite)