Blame sysdeps/ieee754/ldbl-128/e_acosl.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
Packit 6c4009
   the 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_acosl(x)
Packit 6c4009
 * Method :
Packit 6c4009
 *      acos(x)  = pi/2 - asin(x)
Packit 6c4009
 *      acos(-x) = pi/2 + asin(x)
Packit 6c4009
 * For |x| <= 0.375
Packit 6c4009
 *      acos(x) = pi/2 - asin(x)
Packit 6c4009
 * Between .375 and .5 the approximation is
Packit 6c4009
 *      acos(0.4375 + x) = acos(0.4375) + x P(x) / Q(x)
Packit 6c4009
 * Between .5 and .625 the approximation is
Packit 6c4009
 *      acos(0.5625 + x) = acos(0.5625) + x rS(x) / sS(x)
Packit 6c4009
 * For x > 0.625,
Packit 6c4009
 *      acos(x) = 2 asin(sqrt((1-x)/2))
Packit 6c4009
 *      computed with an extended precision square root in the leading term.
Packit 6c4009
 * For x < -0.625
Packit 6c4009
 *      acos(x) = pi - 2 asin(sqrt((1-|x|)/2))
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
 * Functions needed: sqrtl.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
Packit 6c4009
static const _Float128
Packit 6c4009
  one = 1,
Packit 6c4009
  pio2_hi = L(1.5707963267948966192313216916397514420986),
Packit 6c4009
  pio2_lo = L(4.3359050650618905123985220130216759843812E-35),
Packit 6c4009
Packit 6c4009
  /* acos(0.5625 + x) = acos(0.5625) + x rS(x) / sS(x)
Packit 6c4009
     -0.0625 <= x <= 0.0625
Packit 6c4009
     peak relative error 3.3e-35  */
Packit 6c4009
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
  acosr5625 = L(9.7338991014954640492751132535550279812151E-1),
Packit 6c4009
  pimacosr5625 = L(2.1682027434402468335351320579240000860757E0),
Packit 6c4009
Packit 6c4009
  /* acos(0.4375 + x) = acos(0.4375) + x rS(x) / sS(x)
Packit 6c4009
     -0.0625 <= x <= 0.0625
Packit 6c4009
     peak relative error 2.1e-35  */
Packit 6c4009
Packit 6c4009
  P0 =  L(2.177690192235413635229046633751390484892E0),
Packit 6c4009
  P1 = L(-2.848698225706605746657192566166142909573E1),
Packit 6c4009
  P2 =  L(1.040076477655245590871244795403659880304E2),
Packit 6c4009
  P3 = L(-1.400087608918906358323551402881238180553E2),
Packit 6c4009
  P4 =  L(2.221047917671449176051896400503615543757E1),
Packit 6c4009
  P5 =  L(9.643714856395587663736110523917499638702E1),
Packit 6c4009
  P6 = L(-5.158406639829833829027457284942389079196E1),
Packit 6c4009
  P7 = L(-1.578651828337585944715290382181219741813E1),
Packit 6c4009
  P8 =  L(1.093632715903802870546857764647931045906E1),
Packit 6c4009
  P9 =  L(5.448925479898460003048760932274085300103E-1),
Packit 6c4009
  P10 = L(-3.315886001095605268470690485170092986337E-1),
Packit 6c4009
  Q0 = L(-1.958219113487162405143608843774587557016E0),
Packit 6c4009
  Q1 =  L(2.614577866876185080678907676023269360520E1),
Packit 6c4009
  Q2 = L(-9.990858606464150981009763389881793660938E1),
Packit 6c4009
  Q3 =  L(1.443958741356995763628660823395334281596E2),
Packit 6c4009
  Q4 = L(-3.206441012484232867657763518369723873129E1),
Packit 6c4009
  Q5 = L(-1.048560885341833443564920145642588991492E2),
Packit 6c4009
  Q6 =  L(6.745883931909770880159915641984874746358E1),
Packit 6c4009
  Q7 =  L(1.806809656342804436118449982647641392951E1),
Packit 6c4009
  Q8 = L(-1.770150690652438294290020775359580915464E1),
Packit 6c4009
  Q9 = L(-5.659156469628629327045433069052560211164E-1),
Packit 6c4009
  /* 1.000000000000000000000000000000000000000E0 */
Packit 6c4009
Packit 6c4009
  acosr4375 = L(1.1179797320499710475919903296900511518755E0),
Packit 6c4009
  pimacosr4375 = L(2.0236129215398221908706530535894517323217E0),
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
_Float128
Packit 6c4009
__ieee754_acosl (_Float128 x)
Packit 6c4009
{
Packit 6c4009
  _Float128 z, r, w, p, q, s, t, f2;
Packit 6c4009
  int32_t ix, sign;
Packit 6c4009
  ieee854_long_double_shape_type u;
Packit 6c4009
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
	{			/* |x| == 1 */
Packit 6c4009
	  if ((sign & 0x80000000) == 0)
Packit 6c4009
	    return 0.0;		/* acos(1) = 0  */
Packit 6c4009
	  else
Packit 6c4009
	    return (2.0 * pio2_hi) + (2.0 * pio2_lo);	/* acos(-1)= pi */
Packit 6c4009
	}
Packit 6c4009
      return (x - x) / (x - x);	/* acos(|x| > 1) is NaN */
Packit 6c4009
    }
Packit 6c4009
  else if (ix < 0x3ffe0000)	/* |x| < 0.5 */
Packit 6c4009
    {
Packit 6c4009
      if (ix < 0x3f8e0000)	/* |x| < 2**-113 */
Packit 6c4009
	return pio2_hi + pio2_lo;
Packit 6c4009
      if (ix < 0x3ffde000)	/* |x| < .4375 */
Packit 6c4009
	{
Packit 6c4009
	  /* Arcsine of x.  */
Packit 6c4009
	  z = x * x;
Packit 6c4009
	  p = (((((((((pS9 * z
Packit 6c4009
		       + pS8) * z
Packit 6c4009
		      + pS7) * z
Packit 6c4009
		     + pS6) * z
Packit 6c4009
		    + pS5) * z
Packit 6c4009
		   + pS4) * z
Packit 6c4009
		  + pS3) * z
Packit 6c4009
		 + pS2) * z
Packit 6c4009
		+ pS1) * z
Packit 6c4009
	       + pS0) * z;
Packit 6c4009
	  q = (((((((( z
Packit 6c4009
		       + qS8) * z
Packit 6c4009
		     + qS7) * z
Packit 6c4009
		    + qS6) * z
Packit 6c4009
		   + qS5) * z
Packit 6c4009
		  + qS4) * z
Packit 6c4009
		 + qS3) * z
Packit 6c4009
		+ qS2) * z
Packit 6c4009
	       + qS1) * z
Packit 6c4009
	    + qS0;
Packit 6c4009
	  r = x + x * p / q;
Packit 6c4009
	  z = pio2_hi - (r - pio2_lo);
Packit 6c4009
	  return z;
Packit 6c4009
	}
Packit 6c4009
      /* .4375 <= |x| < .5 */
Packit 6c4009
      t = u.value - L(0.4375);
Packit 6c4009
      p = ((((((((((P10 * t
Packit 6c4009
		    + P9) * t
Packit 6c4009
		   + P8) * t
Packit 6c4009
		  + P7) * t
Packit 6c4009
		 + P6) * t
Packit 6c4009
		+ P5) * t
Packit 6c4009
	       + P4) * t
Packit 6c4009
	      + P3) * t
Packit 6c4009
	     + P2) * t
Packit 6c4009
	    + P1) * t
Packit 6c4009
	   + P0) * t;
Packit 6c4009
Packit 6c4009
      q = (((((((((t
Packit 6c4009
		   + Q9) * t
Packit 6c4009
		  + Q8) * t
Packit 6c4009
		 + Q7) * t
Packit 6c4009
		+ Q6) * t
Packit 6c4009
	       + Q5) * t
Packit 6c4009
	      + Q4) * t
Packit 6c4009
	     + Q3) * t
Packit 6c4009
	    + Q2) * t
Packit 6c4009
	   + Q1) * t
Packit 6c4009
	+ Q0;
Packit 6c4009
      r = p / q;
Packit 6c4009
      if (sign & 0x80000000)
Packit 6c4009
	r = pimacosr4375 - r;
Packit 6c4009
      else
Packit 6c4009
	r = acosr4375 + r;
Packit 6c4009
      return r;
Packit 6c4009
    }
Packit 6c4009
  else if (ix < 0x3ffe4000)	/* |x| < 0.625 */
Packit 6c4009
    {
Packit 6c4009
      t = u.value - L(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
      if (sign & 0x80000000)
Packit 6c4009
	r = pimacosr5625 - p / q;
Packit 6c4009
      else
Packit 6c4009
	r = acosr5625 + p / q;
Packit 6c4009
      return r;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {				/* |x| >= .625 */
Packit 6c4009
      z = (one - u.value) * 0.5;
Packit 6c4009
      s = sqrtl (z);
Packit 6c4009
      /* Compute an extended precision square root from
Packit 6c4009
	 the Newton iteration  s -> 0.5 * (s + z / s).
Packit 6c4009
	 The change w from s to the improved value is
Packit 6c4009
	    w = 0.5 * (s + z / s) - s  = (s^2 + z)/2s - s = (z - s^2)/2s.
Packit 6c4009
	  Express s = f1 + f2 where f1 * f1 is exactly representable.
Packit 6c4009
	  w = (z - s^2)/2s = (z - f1^2 - 2 f1 f2 - f2^2)/2s .
Packit 6c4009
	  s + w has extended precision.  */
Packit 6c4009
      u.value = s;
Packit 6c4009
      u.parts32.w2 = 0;
Packit 6c4009
      u.parts32.w3 = 0;
Packit 6c4009
      f2 = s - u.value;
Packit 6c4009
      w = z - u.value * u.value;
Packit 6c4009
      w = w - 2.0 * u.value * f2;
Packit 6c4009
      w = w - f2 * f2;
Packit 6c4009
      w = w / (2.0 * s);
Packit 6c4009
      /* Arcsine of s.  */
Packit 6c4009
      p = (((((((((pS9 * z
Packit 6c4009
		   + pS8) * z
Packit 6c4009
		  + pS7) * z
Packit 6c4009
		 + pS6) * z
Packit 6c4009
		+ pS5) * z
Packit 6c4009
	       + pS4) * z
Packit 6c4009
	      + pS3) * z
Packit 6c4009
	     + pS2) * z
Packit 6c4009
	    + pS1) * z
Packit 6c4009
	   + pS0) * z;
Packit 6c4009
      q = (((((((( z
Packit 6c4009
		   + qS8) * z
Packit 6c4009
		 + qS7) * z
Packit 6c4009
		+ qS6) * z
Packit 6c4009
	       + qS5) * z
Packit 6c4009
	      + qS4) * z
Packit 6c4009
	     + qS3) * z
Packit 6c4009
	    + qS2) * z
Packit 6c4009
	   + qS1) * z
Packit 6c4009
	+ qS0;
Packit 6c4009
      r = s + (w + s * p / q);
Packit 6c4009
Packit 6c4009
      if (sign & 0x80000000)
Packit 6c4009
	w = pio2_hi + (pio2_lo - r);
Packit 6c4009
      else
Packit 6c4009
	w = r;
Packit 6c4009
      return 2.0 * w;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
strong_alias (__ieee754_acosl, __acosl_finite)