/* unity.c
*
* Relative error approximations for function arguments near
* unity.
*
* log1p(x) = log(1+x)
* expm1(x) = exp(x) - 1
* cosm1(x) = cos(x) - 1
*
*/
#include <config.h>
#include <gnan.h>
#include "mconf.h"
#ifdef INFINITIES
extern double INFINITY;
#endif
/* log1p(x) = log(1 + x) */
/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
* 1/sqrt(2) <= x < sqrt(2)
* Theoretical peak relative error = 2.32e-20
*/
static double LP[] = {
4.5270000862445199635215E-5,
4.9854102823193375972212E-1,
6.5787325942061044846969E0,
2.9911919328553073277375E1,
6.0949667980987787057556E1,
5.7112963590585538103336E1,
2.0039553499201281259648E1,
};
static double LQ[] = {
/* 1.0000000000000000000000E0,*/
1.5062909083469192043167E1,
8.3047565967967209469434E1,
2.2176239823732856465394E2,
3.0909872225312059774938E2,
2.1642788614495947685003E2,
6.0118660497603843919306E1,
};
#define SQRTH 0.70710678118654752440
#define SQRT2 1.41421356237309504880
double
log1p (double x)
{
double z;
z = 1.0 + x;
if ((z < SQRTH) || (z > SQRT2))
return (log (z));
z = x * x;
z = -0.5 * z + x * (z * polevl (x, LP, 6) / p1evl (x, LQ, 6));
return (x + z);
}
/* expm1(x) = exp(x) - 1 */
/* e^x = 1 + 2x P(x^2)/( Q(x^2) - P(x^2) )
* -0.5 <= x <= 0.5
*/
static double EP[3] = {
1.2617719307481059087798E-4,
3.0299440770744196129956E-2,
9.9999999999999999991025E-1,
};
static double EQ[4] = {
3.0019850513866445504159E-6,
2.5244834034968410419224E-3,
2.2726554820815502876593E-1,
2.0000000000000000000897E0,
};
double
expm1 (double x)
{
double r, xx;
if (g_isnan (x))
return (x);
#ifdef INFINITIES
if (x == G_INFINITY)
return (G_INFINITY);
if (x == -G_INFINITY)
return (-1.0);
#endif
if ((x < -0.5) || (x > 0.5))
return (exp (x) - 1.0);
xx = x * x;
r = x * polevl (xx, EP, 2);
r = r / (polevl (xx, EQ, 3) - r);
return (r + r);
}
/* cosm1(x) = cos(x) - 1 */
static double coscof[7] = {
4.7377507964246204691685E-14,
-1.1470284843425359765671E-11,
2.0876754287081521758361E-9,
-2.7557319214999787979814E-7,
2.4801587301570552304991E-5,
-1.3888888888888872993737E-3,
4.1666666666666666609054E-2,
};
extern double PIO4;
double
cosm1 (double x)
{
double xx;
if ((x < -PIO4) || (x > PIO4))
return (cos (x) - 1.0);
xx = x * x;
xx = -0.5 * xx + xx * xx * polevl (xx, coscof, 6);
return xx;
}
syntax highlighted by Code2HTML, v. 0.9.1