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

Packit 6c4009
/*							cbrtl.c
Packit 6c4009
 *
Packit 6c4009
 *	Cube root, long double precision
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 * SYNOPSIS:
Packit 6c4009
 *
Packit 6c4009
 * long double x, y, cbrtl();
Packit 6c4009
 *
Packit 6c4009
 * y = cbrtl( x );
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 * DESCRIPTION:
Packit 6c4009
 *
Packit 6c4009
 * Returns the cube root of the argument, which may be negative.
Packit 6c4009
 *
Packit 6c4009
 * Range reduction involves determining the power of 2 of
Packit 6c4009
 * the argument.  A polynomial of degree 2 applied to the
Packit 6c4009
 * mantissa, and multiplication by the cube root of 1, 2, or 4
Packit 6c4009
 * approximates the root to within about 0.1%.  Then Newton's
Packit 6c4009
 * iteration is used three times to converge to an accurate
Packit 6c4009
 * result.
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 * ACCURACY:
Packit 6c4009
 *
Packit 6c4009
 *                      Relative error:
Packit 6c4009
 * arithmetic   domain     # trials      peak         rms
Packit 6c4009
 *    IEEE       -8,8       100000      1.3e-34     3.9e-35
Packit 6c4009
 *    IEEE    exp(+-707)    100000      1.3e-34     4.3e-35
Packit 6c4009
 *
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
Cephes Math Library Release 2.2: January, 1991
Packit 6c4009
Copyright 1984, 1991 by Stephen L. Moshier
Packit 6c4009
Adapted for glibc October, 2001.
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
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
#include <libm-alias-ldouble.h>
Packit 6c4009
Packit 6c4009
static const _Float128 CBRT2 = L(1.259921049894873164767210607278228350570251);
Packit 6c4009
static const _Float128 CBRT4 = L(1.587401051968199474751705639272308260391493);
Packit 6c4009
static const _Float128 CBRT2I = L(0.7937005259840997373758528196361541301957467);
Packit 6c4009
static const _Float128 CBRT4I = L(0.6299605249474365823836053036391141752851257);
Packit 6c4009
Packit 6c4009
Packit 6c4009
_Float128
Packit 6c4009
__cbrtl (_Float128 x)
Packit 6c4009
{
Packit 6c4009
  int e, rem, sign;
Packit 6c4009
  _Float128 z;
Packit 6c4009
Packit 6c4009
  if (!isfinite (x))
Packit 6c4009
    return x + x;
Packit 6c4009
Packit 6c4009
  if (x == 0)
Packit 6c4009
    return (x);
Packit 6c4009
Packit 6c4009
  if (x > 0)
Packit 6c4009
    sign = 1;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      sign = -1;
Packit 6c4009
      x = -x;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  z = x;
Packit 6c4009
 /* extract power of 2, leaving mantissa between 0.5 and 1  */
Packit 6c4009
  x = __frexpl (x, &e);
Packit 6c4009
Packit 6c4009
  /* Approximate cube root of number between .5 and 1,
Packit 6c4009
     peak relative error = 1.2e-6  */
Packit 6c4009
  x = ((((L(1.3584464340920900529734e-1) * x
Packit 6c4009
	  - L(6.3986917220457538402318e-1)) * x
Packit 6c4009
	 + L(1.2875551670318751538055e0)) * x
Packit 6c4009
	- L(1.4897083391357284957891e0)) * x
Packit 6c4009
       + L(1.3304961236013647092521e0)) * x + L(3.7568280825958912391243e-1);
Packit 6c4009
Packit 6c4009
  /* exponent divided by 3 */
Packit 6c4009
  if (e >= 0)
Packit 6c4009
    {
Packit 6c4009
      rem = e;
Packit 6c4009
      e /= 3;
Packit 6c4009
      rem -= 3 * e;
Packit 6c4009
      if (rem == 1)
Packit 6c4009
	x *= CBRT2;
Packit 6c4009
      else if (rem == 2)
Packit 6c4009
	x *= CBRT4;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {				/* argument less than 1 */
Packit 6c4009
      e = -e;
Packit 6c4009
      rem = e;
Packit 6c4009
      e /= 3;
Packit 6c4009
      rem -= 3 * e;
Packit 6c4009
      if (rem == 1)
Packit 6c4009
	x *= CBRT2I;
Packit 6c4009
      else if (rem == 2)
Packit 6c4009
	x *= CBRT4I;
Packit 6c4009
      e = -e;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* multiply by power of 2 */
Packit 6c4009
  x = __ldexpl (x, e);
Packit 6c4009
Packit 6c4009
  /* Newton iteration */
Packit 6c4009
  x -= (x - (z / (x * x))) * L(0.3333333333333333333333333333333333333333);
Packit 6c4009
  x -= (x - (z / (x * x))) * L(0.3333333333333333333333333333333333333333);
Packit 6c4009
  x -= (x - (z / (x * x))) * L(0.3333333333333333333333333333333333333333);
Packit 6c4009
Packit 6c4009
  if (sign < 0)
Packit 6c4009
    x = -x;
Packit 6c4009
  return (x);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
libm_alias_ldouble (__cbrt, cbrt)