Blame sysdeps/ieee754/dbl-64/e_exp2.c

Packit Service 82fcde
/* Double-precision floating point 2^x.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* The basic design here is from
Packit Service 82fcde
   Shmuel Gal and Boris Bachelis, "An Accurate Elementary Mathematical
Packit Service 82fcde
   Library for the IEEE Floating Point Standard", ACM Trans. Math. Soft.,
Packit Service 82fcde
   17 (1), March 1991, pp. 26-45.
Packit Service 82fcde
   It has been slightly modified to compute 2^x instead of e^x.
Packit Service 82fcde
   */
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <float.h>
Packit Service 82fcde
#include <ieee754.h>
Packit Service 82fcde
#include <math.h>
Packit Service 82fcde
#include <fenv.h>
Packit Service 82fcde
#include <inttypes.h>
Packit Service 82fcde
#include <math-barriers.h>
Packit Service 82fcde
#include <math_private.h>
Packit Service 82fcde
#include <math-underflow.h>
Packit Service 82fcde
Packit Service 82fcde
#include "t_exp2.h"
Packit Service 82fcde
Packit Service 82fcde
static const double TWO1023 = 8.988465674311579539e+307;
Packit Service 82fcde
static const double TWOM1000 = 9.3326361850321887899e-302;
Packit Service 82fcde
Packit Service 82fcde
double
Packit Service 82fcde
__ieee754_exp2 (double x)
Packit Service 82fcde
{
Packit Service 82fcde
  static const double himark = (double) DBL_MAX_EXP;
Packit Service 82fcde
  static const double lomark = (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1);
Packit Service 82fcde
Packit Service 82fcde
  /* Check for usual case.  */
Packit Service 82fcde
  if (__glibc_likely (isless (x, himark)))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Exceptional cases:  */
Packit Service 82fcde
      if (__glibc_unlikely (!isgreaterequal (x, lomark)))
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (isinf (x))
Packit Service 82fcde
	    /* e^-inf == 0, with no error.  */
Packit Service 82fcde
	    return 0;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    /* Underflow */
Packit Service 82fcde
	    return TWOM1000 * TWOM1000;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      static const double THREEp42 = 13194139533312.0;
Packit Service 82fcde
      int tval, unsafe;
Packit Service 82fcde
      double rx, x22, result;
Packit Service 82fcde
      union ieee754_double ex2_u, scale_u;
Packit Service 82fcde
Packit Service 82fcde
      if (fabs (x) < DBL_EPSILON / 4.0)
Packit Service 82fcde
	return 1.0 + x;
Packit Service 82fcde
Packit Service 82fcde
      {
Packit Service 82fcde
	SET_RESTORE_ROUND_NOEX (FE_TONEAREST);
Packit Service 82fcde
Packit Service 82fcde
	/* 1. Argument reduction.
Packit Service 82fcde
	   Choose integers ex, -256 <= t < 256, and some real
Packit Service 82fcde
	   -1/1024 <= x1 <= 1024 so that
Packit Service 82fcde
	   x = ex + t/512 + x1.
Packit Service 82fcde
Packit Service 82fcde
	   First, calculate rx = ex + t/512.  */
Packit Service 82fcde
	rx = x + THREEp42;
Packit Service 82fcde
	rx -= THREEp42;
Packit Service 82fcde
	x -= rx;  /* Compute x=x1. */
Packit Service 82fcde
	/* Compute tval = (ex*512 + t)+256.
Packit Service 82fcde
	   Now, t = (tval mod 512)-256 and ex=tval/512  [that's mod, NOT %;
Packit Service 82fcde
	   and /-round-to-nearest not the usual c integer /].  */
Packit Service 82fcde
	tval = (int) (rx * 512.0 + 256.0);
Packit Service 82fcde
Packit Service 82fcde
	/* 2. Adjust for accurate table entry.
Packit Service 82fcde
	   Find e so that
Packit Service 82fcde
	   x = ex + t/512 + e + x2
Packit Service 82fcde
	   where -1e6 < e < 1e6, and
Packit Service 82fcde
	   (double)(2^(t/512+e))
Packit Service 82fcde
	   is accurate to one part in 2^-64.  */
Packit Service 82fcde
Packit Service 82fcde
	/* 'tval & 511' is the same as 'tval%512' except that it's always
Packit Service 82fcde
	   positive.
Packit Service 82fcde
	   Compute x = x2.  */
Packit Service 82fcde
	x -= exp2_deltatable[tval & 511];
Packit Service 82fcde
Packit Service 82fcde
	/* 3. Compute ex2 = 2^(t/512+e+ex).  */
Packit Service 82fcde
	ex2_u.d = exp2_accuratetable[tval & 511];
Packit Service 82fcde
	tval >>= 9;
Packit Service 82fcde
	/* x2 is an integer multiple of 2^-54; avoid intermediate
Packit Service 82fcde
	   underflow from the calculation of x22 * x.  */
Packit Service 82fcde
	unsafe = abs (tval) >= -DBL_MIN_EXP - 56;
Packit Service 82fcde
	ex2_u.ieee.exponent += tval >> unsafe;
Packit Service 82fcde
	scale_u.d = 1.0;
Packit Service 82fcde
	scale_u.ieee.exponent += tval - (tval >> unsafe);
Packit Service 82fcde
Packit Service 82fcde
	/* 4. Approximate 2^x2 - 1, using a fourth-degree polynomial,
Packit Service 82fcde
	   with maximum error in [-2^-10-2^-30,2^-10+2^-30]
Packit Service 82fcde
	   less than 10^-19.  */
Packit Service 82fcde
Packit Service 82fcde
	x22 = (((.0096181293647031180
Packit Service 82fcde
		 * x + .055504110254308625)
Packit Service 82fcde
		* x + .240226506959100583)
Packit Service 82fcde
	       * x + .69314718055994495) * ex2_u.d;
Packit Service 82fcde
	math_opt_barrier (x22);
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
      /* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex).  */
Packit Service 82fcde
      result = x22 * x + ex2_u.d;
Packit Service 82fcde
Packit Service 82fcde
      if (!unsafe)
Packit Service 82fcde
	return result;
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  result *= scale_u.d;
Packit Service 82fcde
	  math_check_force_underflow_nonneg (result);
Packit Service 82fcde
	  return result;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    /* Return x, if x is a NaN or Inf; or overflow, otherwise.  */
Packit Service 82fcde
    return TWO1023 * x;
Packit Service 82fcde
}
Packit Service 82fcde
strong_alias (__ieee754_exp2, __exp2_finite)