Blame sysdeps/ieee754/ldbl-128/e_asinl.c

Packit 6c4009
/*
Packit 6c4009
 * ====================================================
Packit 6c4009
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit 6c4009
 * Permission to use, copy, modify, and distribute this
Packit 6c4009
 * software is freely granted, provided that this notice
Packit 6c4009
 * is preserved.
Packit 6c4009
 * ====================================================
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
  Long double expansions are
Packit 6c4009
  Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
Packit 6c4009
  and are incorporated herein by permission of the author.  The author
Packit 6c4009
  reserves the right to distribute this material elsewhere under different
Packit 6c4009
  copying permissions.  These modifications are distributed here under the
Packit 6c4009
  following terms:
Packit 6c4009
Packit 6c4009
    This library is free software; you can redistribute it and/or
Packit 6c4009
    modify it under the terms of the GNU Lesser General Public
Packit 6c4009
    License as published by the Free Software Foundation; either
Packit 6c4009
    version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
    This library is distributed in the hope that it will be useful,
Packit 6c4009
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
    Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
    You should have received a copy of the GNU Lesser General Public
Packit 6c4009
    License along with this library; if not, see
Packit 6c4009
    <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* __ieee754_asin(x)
Packit 6c4009
 * Method :
Packit 6c4009
 *	Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
Packit 6c4009
 *	we approximate asin(x) on [0,0.5] by
Packit 6c4009
 *		asin(x) = x + x*x^2*R(x^2)
Packit 6c4009
 *      Between .5 and .625 the approximation is
Packit 6c4009
 *              asin(0.5625 + x) = asin(0.5625) + x rS(x) / sS(x)
Packit 6c4009
 *	For x in [0.625,1]
Packit 6c4009
 *		asin(x) = pi/2-2*asin(sqrt((1-x)/2))
Packit 6c4009
 *	Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
Packit 6c4009
 *	then for x>0.98
Packit 6c4009
 *		asin(x) = pi/2 - 2*(s+s*z*R(z))
Packit 6c4009
 *			= pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
Packit 6c4009
 *	For x<=0.98, let pio4_hi = pio2_hi/2, then
Packit 6c4009
 *		f = hi part of s;
Packit 6c4009
 *		c = sqrt(z) - f = (z-f*f)/(s+f) 	...f+c=sqrt(z)
Packit 6c4009
 *	and
Packit 6c4009
 *		asin(x) = pi/2 - 2*(s+s*z*R(z))
Packit 6c4009
 *			= pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
Packit 6c4009
 *			= pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
Packit 6c4009
 *
Packit 6c4009
 * Special cases:
Packit 6c4009
 *	if x is NaN, return x itself;
Packit 6c4009
 *	if |x|>1, return NaN with invalid signal.
Packit 6c4009
 *
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
Packit 6c4009
#include <float.h>
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math-barriers.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
#include <math-underflow.h>
Packit 6c4009
Packit 6c4009
static const _Float128
Packit 6c4009
  one = 1,
Packit 6c4009
  huge = L(1.0e+4932),
Packit 6c4009
  pio2_hi = L(1.5707963267948966192313216916397514420986),
Packit 6c4009
  pio2_lo = L(4.3359050650618905123985220130216759843812E-35),
Packit 6c4009
  pio4_hi = L(7.8539816339744830961566084581987569936977E-1),
Packit 6c4009
Packit 6c4009
	/* coefficient for R(x^2) */
Packit 6c4009
Packit 6c4009
  /* asin(x) = x + x^3 pS(x^2) / qS(x^2)
Packit 6c4009
     0 <= x <= 0.5
Packit 6c4009
     peak relative error 1.9e-35  */
Packit 6c4009
  pS0 = L(-8.358099012470680544198472400254596543711E2),
Packit 6c4009
  pS1 =  L(3.674973957689619490312782828051860366493E3),
Packit 6c4009
  pS2 = L(-6.730729094812979665807581609853656623219E3),
Packit 6c4009
  pS3 =  L(6.643843795209060298375552684423454077633E3),
Packit 6c4009
  pS4 = L(-3.817341990928606692235481812252049415993E3),
Packit 6c4009
  pS5 =  L(1.284635388402653715636722822195716476156E3),
Packit 6c4009
  pS6 = L(-2.410736125231549204856567737329112037867E2),
Packit 6c4009
  pS7 =  L(2.219191969382402856557594215833622156220E1),
Packit 6c4009
  pS8 = L(-7.249056260830627156600112195061001036533E-1),
Packit 6c4009
  pS9 =  L(1.055923570937755300061509030361395604448E-3),
Packit 6c4009
Packit 6c4009
  qS0 = L(-5.014859407482408326519083440151745519205E3),
Packit 6c4009
  qS1 =  L(2.430653047950480068881028451580393430537E4),
Packit 6c4009
  qS2 = L(-4.997904737193653607449250593976069726962E4),
Packit 6c4009
  qS3 =  L(5.675712336110456923807959930107347511086E4),
Packit 6c4009
  qS4 = L(-3.881523118339661268482937768522572588022E4),
Packit 6c4009
  qS5 =  L(1.634202194895541569749717032234510811216E4),
Packit 6c4009
  qS6 = L(-4.151452662440709301601820849901296953752E3),
Packit 6c4009
  qS7 =  L(5.956050864057192019085175976175695342168E2),
Packit 6c4009
  qS8 = L(-4.175375777334867025769346564600396877176E1),
Packit 6c4009
  /* 1.000000000000000000000000000000000000000E0 */
Packit 6c4009
Packit 6c4009
  /* asin(0.5625 + x) = asin(0.5625) + x rS(x) / sS(x)
Packit 6c4009
     -0.0625 <= x <= 0.0625
Packit 6c4009
     peak relative error 3.3e-35  */
Packit 6c4009
  rS0 = L(-5.619049346208901520945464704848780243887E0),
Packit 6c4009
  rS1 =  L(4.460504162777731472539175700169871920352E1),
Packit 6c4009
  rS2 = L(-1.317669505315409261479577040530751477488E2),
Packit 6c4009
  rS3 =  L(1.626532582423661989632442410808596009227E2),
Packit 6c4009
  rS4 = L(-3.144806644195158614904369445440583873264E1),
Packit 6c4009
  rS5 = L(-9.806674443470740708765165604769099559553E1),
Packit 6c4009
  rS6 =  L(5.708468492052010816555762842394927806920E1),
Packit 6c4009
  rS7 =  L(1.396540499232262112248553357962639431922E1),
Packit 6c4009
  rS8 = L(-1.126243289311910363001762058295832610344E1),
Packit 6c4009
  rS9 = L(-4.956179821329901954211277873774472383512E-1),
Packit 6c4009
  rS10 =  L(3.313227657082367169241333738391762525780E-1),
Packit 6c4009
Packit 6c4009
  sS0 = L(-4.645814742084009935700221277307007679325E0),
Packit 6c4009
  sS1 =  L(3.879074822457694323970438316317961918430E1),
Packit 6c4009
  sS2 = L(-1.221986588013474694623973554726201001066E2),
Packit 6c4009
  sS3 =  L(1.658821150347718105012079876756201905822E2),
Packit 6c4009
  sS4 = L(-4.804379630977558197953176474426239748977E1),
Packit 6c4009
  sS5 = L(-1.004296417397316948114344573811562952793E2),
Packit 6c4009
  sS6 =  L(7.530281592861320234941101403870010111138E1),
Packit 6c4009
  sS7 =  L(1.270735595411673647119592092304357226607E1),
Packit 6c4009
  sS8 = L(-1.815144839646376500705105967064792930282E1),
Packit 6c4009
  sS9 = L(-7.821597334910963922204235247786840828217E-2),
Packit 6c4009
  /*  1.000000000000000000000000000000000000000E0 */
Packit 6c4009
Packit 6c4009
 asinr5625 =  L(5.9740641664535021430381036628424864397707E-1);
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
_Float128
Packit 6c4009
__ieee754_asinl (_Float128 x)
Packit 6c4009
{
Packit 6c4009
  _Float128 t, w, p, q, c, r, s;
Packit 6c4009
  int32_t ix, sign, flag;
Packit 6c4009
  ieee854_long_double_shape_type u;
Packit 6c4009
Packit 6c4009
  flag = 0;
Packit 6c4009
  u.value = x;
Packit 6c4009
  sign = u.parts32.w0;
Packit 6c4009
  ix = sign & 0x7fffffff;
Packit 6c4009
  u.parts32.w0 = ix;    /* |x| */
Packit 6c4009
  if (ix >= 0x3fff0000)	/* |x|>= 1 */
Packit 6c4009
    {
Packit 6c4009
      if (ix == 0x3fff0000
Packit 6c4009
	  && (u.parts32.w1 | u.parts32.w2 | u.parts32.w3) == 0)
Packit 6c4009
	/* asin(1)=+-pi/2 with inexact */
Packit 6c4009
	return x * pio2_hi + x * pio2_lo;
Packit 6c4009
      return (x - x) / (x - x);	/* asin(|x|>1) is NaN */
Packit 6c4009
    }
Packit 6c4009
  else if (ix < 0x3ffe0000) /* |x| < 0.5 */
Packit 6c4009
    {
Packit 6c4009
      if (ix < 0x3fc60000) /* |x| < 2**-57 */
Packit 6c4009
	{
Packit 6c4009
	  math_check_force_underflow (x);
Packit 6c4009
	  _Float128 force_inexact = huge + x;
Packit 6c4009
	  math_force_eval (force_inexact);
Packit 6c4009
	  return x;		/* return x with inexact if x!=0 */
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  t = x * x;
Packit 6c4009
	  /* Mark to use pS, qS later on.  */
Packit 6c4009
	  flag = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else if (ix < 0x3ffe4000) /* 0.625 */
Packit 6c4009
    {
Packit 6c4009
      t = u.value - 0.5625;
Packit 6c4009
      p = ((((((((((rS10 * t
Packit 6c4009
		    + rS9) * t
Packit 6c4009
		   + rS8) * t
Packit 6c4009
		  + rS7) * t
Packit 6c4009
		 + rS6) * t
Packit 6c4009
		+ rS5) * t
Packit 6c4009
	       + rS4) * t
Packit 6c4009
	      + rS3) * t
Packit 6c4009
	     + rS2) * t
Packit 6c4009
	    + rS1) * t
Packit 6c4009
	   + rS0) * t;
Packit 6c4009
Packit 6c4009
      q = ((((((((( t
Packit 6c4009
		    + sS9) * t
Packit 6c4009
		  + sS8) * t
Packit 6c4009
		 + sS7) * t
Packit 6c4009
		+ sS6) * t
Packit 6c4009
	       + sS5) * t
Packit 6c4009
	      + sS4) * t
Packit 6c4009
	     + sS3) * t
Packit 6c4009
	    + sS2) * t
Packit 6c4009
	   + sS1) * t
Packit 6c4009
	+ sS0;
Packit 6c4009
      t = asinr5625 + p / q;
Packit 6c4009
      if ((sign & 0x80000000) == 0)
Packit 6c4009
	return t;
Packit 6c4009
      else
Packit 6c4009
	return -t;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      /* 1 > |x| >= 0.625 */
Packit 6c4009
      w = one - u.value;
Packit 6c4009
      t = w * 0.5;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  p = (((((((((pS9 * t
Packit 6c4009
	       + pS8) * t
Packit 6c4009
	      + pS7) * t
Packit 6c4009
	     + pS6) * t
Packit 6c4009
	    + pS5) * t
Packit 6c4009
	   + pS4) * t
Packit 6c4009
	  + pS3) * t
Packit 6c4009
	 + pS2) * t
Packit 6c4009
	+ pS1) * t
Packit 6c4009
       + pS0) * t;
Packit 6c4009
Packit 6c4009
  q = (((((((( t
Packit 6c4009
	      + qS8) * t
Packit 6c4009
	     + qS7) * t
Packit 6c4009
	    + qS6) * t
Packit 6c4009
	   + qS5) * t
Packit 6c4009
	  + qS4) * t
Packit 6c4009
	 + qS3) * t
Packit 6c4009
	+ qS2) * t
Packit 6c4009
       + qS1) * t
Packit 6c4009
    + qS0;
Packit 6c4009
Packit 6c4009
  if (flag) /* 2^-57 < |x| < 0.5 */
Packit 6c4009
    {
Packit 6c4009
      w = p / q;
Packit 6c4009
      return x + x * w;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  s = sqrtl (t);
Packit 6c4009
  if (ix >= 0x3ffef333) /* |x| > 0.975 */
Packit 6c4009
    {
Packit 6c4009
      w = p / q;
Packit 6c4009
      t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      u.value = s;
Packit 6c4009
      u.parts32.w3 = 0;
Packit 6c4009
      u.parts32.w2 = 0;
Packit 6c4009
      w = u.value;
Packit 6c4009
      c = (t - w * w) / (s + w);
Packit 6c4009
      r = p / q;
Packit 6c4009
      p = 2.0 * s * r - (pio2_lo - 2.0 * c);
Packit 6c4009
      q = pio4_hi - 2.0 * w;
Packit 6c4009
      t = pio4_hi - (p - q);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if ((sign & 0x80000000) == 0)
Packit 6c4009
    return t;
Packit 6c4009
  else
Packit 6c4009
    return -t;
Packit 6c4009
}
Packit 6c4009
strong_alias (__ieee754_asinl, __asinl_finite)