Blame sysdeps/ieee754/ldbl-128ibm/e_log2l.c

Packit 6c4009
/*                                                      log2l.c
Packit 6c4009
 *      Base 2 logarithm, 128-bit long double precision
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 * SYNOPSIS:
Packit 6c4009
 *
Packit 6c4009
 * long double x, y, log2l();
Packit 6c4009
 *
Packit 6c4009
 * y = log2l( x );
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 *
Packit 6c4009
 * DESCRIPTION:
Packit 6c4009
 *
Packit 6c4009
 * Returns the base 2 logarithm of x.
Packit 6c4009
 *
Packit 6c4009
 * The argument is separated into its exponent and fractional
Packit 6c4009
 * parts.  If the exponent is between -1 and +1, the (natural)
Packit 6c4009
 * logarithm of the fraction is approximated by
Packit 6c4009
 *
Packit 6c4009
 *     log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
Packit 6c4009
 *
Packit 6c4009
 * Otherwise, setting  z = 2(x-1)/x+1),
Packit 6c4009
 *
Packit 6c4009
 *     log(x) = z + z^3 P(z)/Q(z).
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      0.5, 2.0     100,000    2.6e-34     4.9e-35
Packit 6c4009
 *    IEEE     exp(+-10000)  100,000    9.6e-35     4.0e-35
Packit 6c4009
 *
Packit 6c4009
 * In the tests over the interval exp(+-10000), the logarithms
Packit 6c4009
 * of the random arguments were uniformly distributed over
Packit 6c4009
 * [-10000, +10000].
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 November, 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 <http://www.gnu.org/licenses/>.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
Packit 6c4009
/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
Packit 6c4009
 * 1/sqrt(2) <= x < sqrt(2)
Packit 6c4009
 * Theoretical peak relative error = 5.3e-37,
Packit 6c4009
 * relative peak error spread = 2.3e-14
Packit 6c4009
 */
Packit 6c4009
static const long double P[13] =
Packit 6c4009
{
Packit 6c4009
  1.313572404063446165910279910527789794488E4L,
Packit 6c4009
  7.771154681358524243729929227226708890930E4L,
Packit 6c4009
  2.014652742082537582487669938141683759923E5L,
Packit 6c4009
  3.007007295140399532324943111654767187848E5L,
Packit 6c4009
  2.854829159639697837788887080758954924001E5L,
Packit 6c4009
  1.797628303815655343403735250238293741397E5L,
Packit 6c4009
  7.594356839258970405033155585486712125861E4L,
Packit 6c4009
  2.128857716871515081352991964243375186031E4L,
Packit 6c4009
  3.824952356185897735160588078446136783779E3L,
Packit 6c4009
  4.114517881637811823002128927449878962058E2L,
Packit 6c4009
  2.321125933898420063925789532045674660756E1L,
Packit 6c4009
  4.998469661968096229986658302195402690910E-1L,
Packit 6c4009
  1.538612243596254322971797716843006400388E-6L
Packit 6c4009
};
Packit 6c4009
static const long double Q[12] =
Packit 6c4009
{
Packit 6c4009
  3.940717212190338497730839731583397586124E4L,
Packit 6c4009
  2.626900195321832660448791748036714883242E5L,
Packit 6c4009
  7.777690340007566932935753241556479363645E5L,
Packit 6c4009
  1.347518538384329112529391120390701166528E6L,
Packit 6c4009
  1.514882452993549494932585972882995548426E6L,
Packit 6c4009
  1.158019977462989115839826904108208787040E6L,
Packit 6c4009
  6.132189329546557743179177159925690841200E5L,
Packit 6c4009
  2.248234257620569139969141618556349415120E5L,
Packit 6c4009
  5.605842085972455027590989944010492125825E4L,
Packit 6c4009
  9.147150349299596453976674231612674085381E3L,
Packit 6c4009
  9.104928120962988414618126155557301584078E2L,
Packit 6c4009
  4.839208193348159620282142911143429644326E1L
Packit 6c4009
/* 1.000000000000000000000000000000000000000E0L, */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
Packit 6c4009
 * where z = 2(x-1)/(x+1)
Packit 6c4009
 * 1/sqrt(2) <= x < sqrt(2)
Packit 6c4009
 * Theoretical peak relative error = 1.1e-35,
Packit 6c4009
 * relative peak error spread 1.1e-9
Packit 6c4009
 */
Packit 6c4009
static const long double R[6] =
Packit 6c4009
{
Packit 6c4009
  1.418134209872192732479751274970992665513E5L,
Packit 6c4009
 -8.977257995689735303686582344659576526998E4L,
Packit 6c4009
  2.048819892795278657810231591630928516206E4L,
Packit 6c4009
 -2.024301798136027039250415126250455056397E3L,
Packit 6c4009
  8.057002716646055371965756206836056074715E1L,
Packit 6c4009
 -8.828896441624934385266096344596648080902E-1L
Packit 6c4009
};
Packit 6c4009
static const long double S[6] =
Packit 6c4009
{
Packit 6c4009
  1.701761051846631278975701529965589676574E6L,
Packit 6c4009
 -1.332535117259762928288745111081235577029E6L,
Packit 6c4009
  4.001557694070773974936904547424676279307E5L,
Packit 6c4009
 -5.748542087379434595104154610899551484314E4L,
Packit 6c4009
  3.998526750980007367835804959888064681098E3L,
Packit 6c4009
 -1.186359407982897997337150403816839480438E2L
Packit 6c4009
/* 1.000000000000000000000000000000000000000E0L, */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static const long double
Packit 6c4009
/* log2(e) - 1 */
Packit 6c4009
LOG2EA = 4.4269504088896340735992468100189213742664595E-1L,
Packit 6c4009
/* sqrt(2)/2 */
Packit 6c4009
SQRTH = 7.071067811865475244008443621048490392848359E-1L;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Evaluate P[n] x^n  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
Packit 6c4009
Packit 6c4009
static long double
Packit 6c4009
neval (long double x, const long double *p, int n)
Packit 6c4009
{
Packit 6c4009
  long double y;
Packit 6c4009
Packit 6c4009
  p += n;
Packit 6c4009
  y = *p--;
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      y = y * x + *p--;
Packit 6c4009
    }
Packit 6c4009
  while (--n > 0);
Packit 6c4009
  return y;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Evaluate x^n+1  +  P[n] x^(n)  +  P[n-1] x^(n-1)  +  ...  +  P[0] */
Packit 6c4009
Packit 6c4009
static long double
Packit 6c4009
deval (long double x, const long double *p, int n)
Packit 6c4009
{
Packit 6c4009
  long double y;
Packit 6c4009
Packit 6c4009
  p += n;
Packit 6c4009
  y = x + *p--;
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      y = y * x + *p--;
Packit 6c4009
    }
Packit 6c4009
  while (--n > 0);
Packit 6c4009
  return y;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
long double
Packit 6c4009
__ieee754_log2l (long double x)
Packit 6c4009
{
Packit 6c4009
  long double z;
Packit 6c4009
  long double y;
Packit 6c4009
  int e;
Packit 6c4009
  int64_t hx;
Packit 6c4009
  double xhi;
Packit 6c4009
Packit 6c4009
/* Test for domain */
Packit 6c4009
  xhi = ldbl_high (x);
Packit 6c4009
  EXTRACT_WORDS64 (hx, xhi);
Packit 6c4009
  if ((hx & 0x7fffffffffffffffLL) == 0)
Packit 6c4009
    return (-1.0L / fabsl (x));		/* log2l(+-0)=-inf  */
Packit 6c4009
  if (hx < 0)
Packit 6c4009
    return (x - x) / (x - x);
Packit 6c4009
  if (hx >= 0x7ff0000000000000LL)
Packit 6c4009
    return (x + x);
Packit 6c4009
Packit 6c4009
  if (x == 1.0L)
Packit 6c4009
    return 0.0L;
Packit 6c4009
Packit 6c4009
/* separate mantissa from exponent */
Packit 6c4009
Packit 6c4009
/* Note, frexp is used so that denormal numbers
Packit 6c4009
 * will be handled properly.
Packit 6c4009
 */
Packit 6c4009
  x = __frexpl (x, &e);
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* logarithm using log(x) = z + z**3 P(z)/Q(z),
Packit 6c4009
 * where z = 2(x-1)/x+1)
Packit 6c4009
 */
Packit 6c4009
  if ((e > 2) || (e < -2))
Packit 6c4009
    {
Packit 6c4009
      if (x < SQRTH)
Packit 6c4009
	{			/* 2( 2x-1 )/( 2x+1 ) */
Packit 6c4009
	  e -= 1;
Packit 6c4009
	  z = x - 0.5L;
Packit 6c4009
	  y = 0.5L * z + 0.5L;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{			/*  2 (x-1)/(x+1)   */
Packit 6c4009
	  z = x - 0.5L;
Packit 6c4009
	  z -= 0.5L;
Packit 6c4009
	  y = 0.5L * x + 0.5L;
Packit 6c4009
	}
Packit 6c4009
      x = z / y;
Packit 6c4009
      z = x * x;
Packit 6c4009
      y = x * (z * neval (z, R, 5) / deval (z, S, 5));
Packit 6c4009
      goto done;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
Packit 6c4009
Packit 6c4009
  if (x < SQRTH)
Packit 6c4009
    {
Packit 6c4009
      e -= 1;
Packit 6c4009
      x = 2.0 * x - 1.0L;	/*  2x - 1  */
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      x = x - 1.0L;
Packit 6c4009
    }
Packit 6c4009
  z = x * x;
Packit 6c4009
  y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
Packit 6c4009
  y = y - 0.5 * z;
Packit 6c4009
Packit 6c4009
done:
Packit 6c4009
Packit 6c4009
/* Multiply log of fraction by log2(e)
Packit 6c4009
 * and base 2 exponent by 1
Packit 6c4009
 */
Packit 6c4009
  z = y * LOG2EA;
Packit 6c4009
  z += x * LOG2EA;
Packit 6c4009
  z += y;
Packit 6c4009
  z += x;
Packit 6c4009
  z += e;
Packit 6c4009
  return (z);
Packit 6c4009
}
Packit 6c4009
strong_alias (__ieee754_log2l, __log2l_finite)