]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/ieee754/flt-32/e_exp2f.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / ieee754 / flt-32 / e_exp2f.c
CommitLineData
63640cb7 1/* Single-precision floating point 2^x.
d4697bc9 2 Copyright (C) 1997-2014 Free Software Foundation, Inc.
63640cb7
UD
3 This file is part of the GNU C Library.
4 Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
63640cb7
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
63640cb7 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
63640cb7
UD
19
20/* The basic design here is from
21 Shmuel Gal and Boris Bachelis, "An Accurate Elementary Mathematical
22 Library for the IEEE Floating Point Standard", ACM Trans. Math. Soft.,
23 17 (1), March 1991, pp. 26-45.
24 It has been slightly modified to compute 2^x instead of e^x, and for
25 single-precision.
26 */
27#ifndef _GNU_SOURCE
28# define _GNU_SOURCE
29#endif
30#include <stdlib.h>
31#include <float.h>
32#include <ieee754.h>
33#include <math.h>
34#include <fenv.h>
35#include <inttypes.h>
36#include <math_private.h>
37
38#include "t_exp2f.h"
39
8ff16245
UD
40static const volatile float TWOM100 = 7.88860905e-31;
41static const volatile float TWO127 = 1.7014118346e+38;
63640cb7
UD
42
43float
44__ieee754_exp2f (float x)
45{
46 static const float himark = (float) FLT_MAX_EXP;
601d2942 47 static const float lomark = (float) (FLT_MIN_EXP - FLT_MANT_DIG - 1);
63640cb7
UD
48
49 /* Check for usual case. */
601d2942 50 if (isless (x, himark) && isgreaterequal (x, lomark))
63640cb7
UD
51 {
52 static const float THREEp14 = 49152.0;
53 int tval, unsafe;
54 float rx, x22, result;
55 union ieee754_float ex2_u, scale_u;
63640cb7 56
eb92c487
RH
57 {
58 SET_RESTORE_ROUND_NOEXF (FE_TONEAREST);
59
60 /* 1. Argument reduction.
61 Choose integers ex, -128 <= t < 128, and some real
62 -1/512 <= x1 <= 1/512 so that
63 x = ex + t/512 + x1.
64
65 First, calculate rx = ex + t/256. */
66 rx = x + THREEp14;
67 rx -= THREEp14;
68 x -= rx; /* Compute x=x1. */
69 /* Compute tval = (ex*256 + t)+128.
70 Now, t = (tval mod 256)-128 and ex=tval/256 [that's mod, NOT %;
71 and /-round-to-nearest not the usual c integer /]. */
72 tval = (int) (rx * 256.0f + 128.0f);
73
74 /* 2. Adjust for accurate table entry.
75 Find e so that
76 x = ex + t/256 + e + x2
77 where -7e-4 < e < 7e-4, and
78 (float)(2^(t/256+e))
79 is accurate to one part in 2^-64. */
80
81 /* 'tval & 255' is the same as 'tval%256' except that it's always
82 positive.
83 Compute x = x2. */
84 x -= __exp2f_deltatable[tval & 255];
85
86 /* 3. Compute ex2 = 2^(t/255+e+ex). */
87 ex2_u.f = __exp2f_atable[tval & 255];
88 tval >>= 8;
89 unsafe = abs(tval) >= -FLT_MIN_EXP - 1;
90 ex2_u.ieee.exponent += tval >> unsafe;
91 scale_u.f = 1.0;
92 scale_u.ieee.exponent += tval - (tval >> unsafe);
93
94 /* 4. Approximate 2^x2 - 1, using a second-degree polynomial,
95 with maximum error in [-2^-9 - 2^-14, 2^-9 + 2^-14]
96 less than 1.3e-10. */
97
98 x22 = (.24022656679f * x + .69314736128f) * ex2_u.f;
99 }
63640cb7 100
eb92c487 101 /* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex). */
63640cb7
UD
102 result = x22 * x + ex2_u.f;
103
104 if (!unsafe)
105 return result;
106 else
107 return result * scale_u.f;
108 }
109 /* Exceptional cases: */
110 else if (isless (x, himark))
111 {
d9a8d0ab 112 if (__isinf_nsf (x))
63640cb7
UD
113 /* e^-inf == 0, with no error. */
114 return 0;
115 else
116 /* Underflow */
117 return TWOM100 * TWOM100;
118 }
119 else
120 /* Return x, if x is a NaN or Inf; or overflow, otherwise. */
121 return TWO127*x;
122}
0ac5ae23 123strong_alias (__ieee754_exp2f, __exp2f_finite)