/*							exp2l.c
 *
 *	Base 2 exponential function, long double precision
 *
 *
 *
 * SYNOPSIS:
 *
 * long double x, y, exp2l();
 *
 * y = exp2l( x );
 *
 *
 *
 * DESCRIPTION:
 *
 * Returns 2 raised to the x power.
 *
 * Range reduction is accomplished by separating the argument
 * into an integer k and fraction f such that
 *     x    k  f
 *    2  = 2  2.
 *
 * A Pade' form
 *
 *   1 + 2x P(x**2) / (Q(x**2) - x P(x**2) )
 *
 * approximates 2**x in the basic range [-0.5, 0.5].
 *
 *
 * ACCURACY:
 *
 *                      Relative error:
 * arithmetic   domain     # trials      peak         rms
 *    IEEE      +-16300     300000      9.1e-20     2.6e-20
 *
 *
 * See exp.c for comments on error amplification.
 *
 *
 * ERROR MESSAGES:
 *
 *   message         condition      value returned
 * exp2l underflow   x < -16382        0.0
 * exp2l overflow    x >= 16384       MAXNUM
 *
 */


/*
Cephes Math Library Release 2.2:  January, 1991
Copyright 1984, 1991 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/



#include "mconf.h"
static char fname[] = {"exp2l"};

#ifdef UNK
static long double P[] = {
 6.0614853552242266094567E1L,
 3.0286971917562792508623E4L,
 2.0803843631901852422887E6L,
};
static long double Q[] = {
/* 1.0000000000000000000000E0,*/
 1.7492876999891839021063E3L,
 3.2772515434906797273099E5L,
 6.0027204078348487957118E6L,
};
#endif


#ifdef IBMPC
static short P[] = {
0xffd8,0x6ad6,0x9c2b,0xf275,0x4004,
0x3426,0x2dc5,0xf19f,0xec9d,0x400d,
0x7ec0,0xd041,0x02e7,0xfdf4,0x4013,
};
static short Q[] = {
/*0x0000,0x0000,0x0000,0x8000,0x3fff,*/
0x575b,0x9b93,0x34d6,0xdaa9,0x4009,
0xe38d,0x6d74,0xa4f0,0xa005,0x4011,
0xb37e,0xcfba,0x40d0,0xb730,0x4015,
};
#endif

#ifdef MIEEE
static long P[] = {
0x40040000,0xf2759c2b,0x6ad6ffd8,
0x400d0000,0xec9df19f,0x2dc53426,
0x40130000,0xfdf402e7,0xd0417ec0,
};
static long Q[] = {
/*0x3fff0000,0x80000000,0x00000000,*/
0x40090000,0xdaa934d6,0x9b93575b,
0x40110000,0xa005a4f0,0x6d74e38d,
0x40150000,0xb73040d0,0xcfbab37e,
};
#endif

#define MAXL2 16384.0L
#define MINL2 -16382.0L


extern long double MAXNUML;

long double exp2l(x)
long double x;
{
long double px, xx;
int n;
long double polevll(), p1evll(), floorl(), ldexpl();

if( x >= MAXL2)
	{
	mtherr( fname, OVERFLOW );
	return( MAXNUML );
	}

if( x < MINL2 )
	{
	mtherr( fname, UNDERFLOW );
	return(0.0L);
	}

xx = x;	/* save x */
/* separate into integer and fractional parts */
px = floorl(x+0.5L);
n = px;
x = x - px;

/* rational approximation
 * exp2(x) = 1.0 +  2xP(xx)/(Q(xx) - P(xx))
 * where xx = x**2
 */
xx = x * x;
px = x * polevll( xx, P, 2 );
x =  px / ( p1evll( xx, Q, 3 ) - px );
x = 1.0 + ldexpl( x, 1 );

/* scale by power of 2 */
x = ldexpl( x, n );
return(x);
}
