glibc/sysdeps/libm-ieee754/e_exp.c
Ulrich Drepper dc30f46157 Update.
1998-02-13 17:39  Ulrich Drepper  <drepper@cygnus.com>

	* elf/Makefile: Don't use --version-script parameter to link ld.so
	unconditionally.

1998-01-02 04:19  Geoff Keating  <geoffk@ozemail.com.au>

	* math/Makefile: Add t_exp.
	* math/libm-test.c: Tighten accuracy bounds for exp(), correct
	constants.
	* math/test-reduce.c: Remove temporarily, it seems to be broken.
	* sysdeps/libm-ieee754/e_exp.c: Use accurate table method.
	* sysdeps/libm-ieee754/e_expf.c: Use table & double precision for
	better accuracy.
	* sysdeps/libm-ieee754/s_exp2.c: Use better polynomial; correct
	algorithm for very large/very small arguments.
	* sysdeps/libm-ieee754/s_exp2f.c: Use slightly better polynomial;
	correct algorithm for very large/very small arguments; adjust for
	new table.
	* sysdeps/libm-ieee754/t_exp.c: New file.
	* sysdeps/libm-ieee754/t_exp2f.h: Use table with smaller deltas.

	* sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c: Put 'strange test'
	back, with comment that explains what breaks when you remove it :-(.

	* localedata/xfrm-test.c: Avoid integer overflow.

	* stdlib/strfmon.c: char is unsigned, sometimes.

	*sysdeps/powerpc
	* sysdeps/powerpc/Makefile: Remove quad float support.
	* sysdeps/powerpc/q_*.c: Remove, they will become an add-on.
	* sysdeps/powerpc/quad_float.h: Likewise.
	* sysdeps/powerpc/test-arith.c: Likewise.
	* sysdeps/powerpc/test-arithf.c: Likewise.

	* sysdeps/generic/s_exp2.c: Remove, we have this implemented now.
	* sysdeps/generic/s_exp2f.c: Likewise.

	* sysdeps/powerpc/bits/mathinline.h: Use underscores around __asm__,
	don't try anything if _SOFT_FLOAT.

1997-12-31  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* locale/C-ctype.c (_nl_C_LC_CTYPE_class32): Undo last change.
	* locale/programs/ld-ctype.c (CHAR_CLASS32_TRANS): Likewise.
	* wctype/wctype.c: Likewise.
	* wctype/wctype.h (_ISwxxx): Renamed from _ISxxx, all uses
	changed.  They are incompatible with the _ISxxx values from
	<ctype.h> on little endian machines.
	(_ISwbit) [__BYTE_ORDER == __LITTLE_ENDIAN]: Correctly transform
	bit number.  This fixes the real bug and restores the integrity of
	the ctype locale file.
	* wctype/wcfuncs.c: Change all _ISxxx to _ISwxxx.
	* wctype/wcfuncs_l.c: Likewise.
	* wctype/wcextra.c: Likewise.
	* wctype/wctype_l.c [__BYTE_ORDER == __LITTLE_ENDIAN]: Use correct
	byte swapping.

1998-02-09  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.S (errno): Put it
	into .bss segment instead of .common, so that aliases on it work.

	* sysdeps/unix/sysv/linux/i386/sysdep.S (errno): Add .type and
	.size directives, put into .bss segment instead of initializing it
	to 4.

1998-02-12 08:00  H.J. Lu  <hjl@gnu.org>

	* libc.map (gnu_get_libc_release, gnu_get_libc_version): Added.

	* version.c (__gnu_get_libc_release, __gnu_get_libc_version): New
	functions.
	Make names without __ weak aliases.
	(__libc_release, __libc_version): Make them static.

	* include/gnu/libc-version.h: New file.
	* Makefile (headers): Add gnu/libc-version.h.

1998-02-13  Ulrich Drepper  <drepper@cygnus.com>

	* stdlib/stdlib.h (struct drand48_data): Leave X to user macros
	and use x for member name.
	Reported by Daniel Lyddy <daniell@cs.berkeley.edu>.

	* stdlib/drand48.c: Change according to member name change.
	* stdlib/drand48_r.c: Likewise.
	* stdlib/lcong48_r.c: Likewise.
	* stdlib/lrand48.c: Likewise.
	* stdlib/lrand48_r.c: Likewise.
	* stdlib/mrand48.c: Likewise.
	* stdlib/mrand48_r.c: Likewise.
	* stdlib/seed48.c: Likewise.
	* stdlib/seed48_r.c: Likewise.
	* stdlib/srand48_r.c: Likewise.

1998-02-11  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* nss/test-netdb.c: Add some more test cases.

1998-02-13 11:39  Ulrich Drepper  <drepper@cygnus.com>

	* libio/iovsscanf.c: Undo last change modifying errno.

1998-02-12  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* stdio-common/vfscanf.c: Never try to read another character
	after EOF.  Don't decrement read_in after EOF, it wasn't
	incremented in the first place.
	(NEXT_WIDE_CHAR): Set First, not first.

1998-02-06 07:48  H.J. Lu  <hjl@gnu.org>

	* db/Makefile ($(inst_libdir)/libndbm.a,
	$(inst_libdir)/libndbm.so): New targets.
	* db2/Makefile: Likewise.

1998-02-12 08:20  H.J. Lu  <hjl@gnu.org>

	* sysdeps/gnu/errlist.awk (sys_errlist, sys_nerr): Create weak
	aliases if HAVE_ELF or PIC or DO_VERSIONING is not defined.

1998-02-12  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/generic/_G_config.h: Define _G_wchar_t, for C++
	<streambuf.h>.
	* sysdeps/unix/sysv/linux/_G_config.h: Likewise.

1998-02-11  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/unix/make-syscalls.sh: Fix sed pattern when dealing with
	versioned symbols.

1998-02-13 08:14  H.J. Lu  <hjl@gnu.org>

	* libc.map (_dl_global_scope, _dl_lookup_symbol_skip,
	_dl_lookup_versioned_symbol, _dl_lookup_versioned_symbol_skip):
	Added for libdl.so.







	* elf/rtld.map: New file.  Needed to define the GLIBC_2.*

	* manual/socket.texi (Host Address Functions): Clarify description
	* sysdeps/unix/sysv/linux/alpha/bits/time.h (struct timeval):
1998-02-13 17:54:15 +00:00

180 lines
5.1 KiB
C

/* Double-precision floating point e^x.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* How this works:
The basic design here is from
Shmuel Gal and Boris Bachelis, "An Accurate Elementary Mathematical
Library for the IEEE Floating Point Standard", ACM Trans. Math. Soft.,
17 (1), March 1991, pp. 26-45.
The input value, x, is written as
x = n * ln(2)_0 + t/512 + delta[t] + x + n * ln(2)_1
where:
- n is an integer, 1024 >= n >= -1075;
- ln(2)_0 is the first 43 bits of ln(2), and ln(2)_1 is the remainder, so
that |ln(2)_1| < 2^-32;
- t is an integer, 177 >= t >= -177
- delta is based on a table entry, delta[t] < 2^-28
- x is whatever is left, |x| < 2^-10
Then e^x is approximated as
e^x = 2^n_1 ( 2^n_0 e^(t/512 + delta[t])
+ ( 2^n_0 e^(t/512 + delta[t])
* ( p(x + n * ln(2)_1)
- n*ln(2)_1
- n*ln(2)_1 * p(x + n * ln(2)_1) ) ) )
where
- p(x) is a polynomial approximating e(x)-1;
- e^(t/512 + delta[t]) is obtained from a table;
- n_1 + n_0 = n, so that |n_0| < DBL_MIN_EXP-1.
If it happens that n_1 == 0 (this is the usual case), that multiplication
is omitted.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <float.h>
#include <ieee754.h>
#include <math.h>
#include <fenv.h>
#include <inttypes.h>
#include <math_private.h>
extern const float __exp_deltatable[178];
extern const double __exp_atable[355] /* __attribute__((mode(DF))) */;
static const volatile double TWO1023 = 8.988465674311579539e+307;
static const volatile double TWOM1000 = 9.3326361850321887899e-302;
double
__ieee754_exp (double x)
{
static const uint32_t a_minf = 0xff800000;
static const double himark = 709.7827128933840868;
static const double lomark = -745.1332191019412221;
/* Check for usual case. */
if (isless (x, himark) && isgreater (x, lomark))
{
static const float TWO43 = 8796093022208.0;
static const float TWO52 = 4503599627370496.0;
/* 1/ln(2). */
static const double M_1_LN2 = 1.442695040888963387;
/* ln(2), part 1 */
static const double M_LN2_0 = .6931471805598903302;
/* ln(2), part 2 */
static const double M_LN2_1 = 5.497923018708371155e-14;
int tval, unsafe, n_i;
double x22, n, t, dely, result;
union ieee754_double ex2_u, scale_u;
fenv_t oldenv;
feholdexcept (&oldenv);
fesetround (FE_TONEAREST);
/* Calculate n. */
if (x >= 0)
{
n = x * M_1_LN2 + TWO52;
n -= TWO52;
}
else
{
n = x * M_1_LN2 - TWO52;
n += TWO52;
}
x = x - n*M_LN2_0;
if (x >= 0)
{
/* Calculate t/512. */
t = x + TWO43;
t -= TWO43;
x -= t;
/* Compute tval = t. */
tval = (int) (t * 512.0);
x -= __exp_deltatable[tval];
}
else
{
/* As above, but x is negative. */
t = x - TWO43;
t += TWO43;
x -= t;
tval = (int) (t * 512.0);
x += __exp_deltatable[-tval];
}
/* Now, the variable x contains x + n*ln(2)_1. */
dely = n*M_LN2_1;
/* Compute ex2 = 2^n_0 e^(t/512+delta[t]). */
ex2_u.d = __exp_atable[tval+177];
n_i = (int)n;
/* 'unsafe' is 1 iff n_1 != 0. */
unsafe = abs(n_i) >= -DBL_MIN_EXP - 1;
ex2_u.ieee.exponent += n_i >> unsafe;
/* Compute scale = 2^n_1. */
scale_u.d = 1.0;
scale_u.ieee.exponent += n_i - (n_i >> unsafe);
/* Approximate e^x2 - 1, using a fourth-degree polynomial,
with maximum error in [-2^-10-2^-28,2^-10+2^-28]
less than 4.9e-19. */
x22 = (((0.04166666898464281565
* x + 0.1666666766008501610)
* x + 0.499999999999990008)
* x + 0.9999999999999976685) * x;
/* Allow for impact of dely. */
x22 -= dely + dely*x22;
/* Return result. */
fesetenv (&oldenv);
result = x22 * ex2_u.d + ex2_u.d;
if (!unsafe)
return result;
else
return result * scale_u.d;
}
/* Exceptional cases: */
else if (isless (x, himark))
{
if (x == *(const float *) &a_minf)
/* e^-inf == 0, with no error. */
return 0;
else
/* Underflow */
return TWOM1000 * TWOM1000;
}
else
/* Return x, if x is a NaN or Inf; or overflow, otherwise. */
return TWO1023*x;
}