~ubuntu-branches/ubuntu/precise/eglibc/precise

« back to all changes in this revision

Viewing changes to sysdeps/ieee754/dbl-64/e_exp2.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2011-10-04 17:48:26 UTC
  • mfrom: (216.1.23 oneiric)
  • Revision ID: package-import@ubuntu.com-20111004174826-2cyb9ewn3ucymlsx
Tags: 2.13-20ubuntu5
libc6-dev: Don't break the current {gnat,gcj}-4.4-base versons. LP: #853688.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Double-precision floating point 2^x.
2
 
   Copyright (C) 1997,1998,2000,2001,2005,2006,2011
3
 
   Free Software Foundation, Inc.
 
2
   Copyright (C) 1997,1998,2000,2001,2005,2006 Free Software Foundation, Inc.
4
3
   This file is part of the GNU C Library.
5
4
   Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
6
5
 
25
24
   17 (1), March 1991, pp. 26-45.
26
25
   It has been slightly modified to compute 2^x instead of e^x.
27
26
   */
 
27
#ifndef _GNU_SOURCE
 
28
#define _GNU_SOURCE
 
29
#endif
28
30
#include <stdlib.h>
29
31
#include <float.h>
30
32
#include <ieee754.h>
35
37
 
36
38
#include "t_exp2.h"
37
39
 
38
 
static const double TWO1023 = 8.988465674311579539e+307;
39
 
static const double TWOM1000 = 9.3326361850321887899e-302;
 
40
/* XXX I know the assembler generates a warning about incorrect section
 
41
   attributes. But without the attribute here the compiler places the
 
42
   constants in the .data section.  Ideally the constant is placed in
 
43
   .rodata.cst8 so that it can be merged, but gcc sucks, it ICEs when
 
44
   we try to force this section on it.  --drepper  */
 
45
static const volatile double TWO1023 = 8.988465674311579539e+307;
 
46
static const volatile double TWOM1000 = 9.3326361850321887899e-302;
40
47
 
41
48
double
42
49
__ieee754_exp2 (double x)
45
52
  static const double lomark = (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1);
46
53
 
47
54
  /* Check for usual case.  */
48
 
  if (__builtin_expect (isless (x, himark), 1))
 
55
  if (isless (x, himark) && isgreaterequal (x, lomark))
49
56
    {
50
 
      /* Exceptional cases:  */
51
 
      if (__builtin_expect (! isgreaterequal (x, lomark), 0))
52
 
        {
53
 
          if (__isinf (x))
54
 
            /* e^-inf == 0, with no error.  */
55
 
            return 0;
56
 
          else
57
 
            /* Underflow */
58
 
            return TWOM1000 * TWOM1000;
59
 
        }
60
 
 
61
57
      static const double THREEp42 = 13194139533312.0;
62
58
      int tval, unsafe;
63
59
      double rx, x22, result;
64
60
      union ieee754_double ex2_u, scale_u;
65
61
      fenv_t oldenv;
66
62
 
67
 
      libc_feholdexcept_setround (&oldenv, FE_TONEAREST);
 
63
      feholdexcept (&oldenv);
 
64
#ifdef FE_TONEAREST
 
65
      /* If we don't have this, it's too bad.  */
 
66
      fesetround (FE_TONEAREST);
 
67
#endif
68
68
 
69
69
      /* 1. Argument reduction.
70
70
         Choose integers ex, -256 <= t < 256, and some real
108
108
               * x + .055504110254308625)
109
109
              * x + .240226506959100583)
110
110
             * x + .69314718055994495) * ex2_u.d;
111
 
      math_opt_barrier (x22);
112
111
 
113
112
      /* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex).  */
114
 
      libc_fesetenv (&oldenv);
 
113
      fesetenv (&oldenv);
115
114
 
116
115
      result = x22 * x + ex2_u.d;
117
116
 
120
119
      else
121
120
        return result * scale_u.d;
122
121
    }
 
122
  /* Exceptional cases:  */
 
123
  else if (isless (x, himark))
 
124
    {
 
125
      if (__isinf (x))
 
126
        /* e^-inf == 0, with no error.  */
 
127
        return 0;
 
128
      else
 
129
        /* Underflow */
 
130
        return TWOM1000 * TWOM1000;
 
131
    }
123
132
  else
124
133
    /* Return x, if x is a NaN or Inf; or overflow, otherwise.  */
125
134
    return TWO1023*x;
126
135
}
127
 
strong_alias (__ieee754_exp2, __exp2_finite)