View Raw SPL
/*****************************************************************************
* *
* EXPM1.SPL Copyright (C) 2016 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Computes exp(x) - 1 for small x *
* *
* Revisions: 11 May 2016 RRR Creation *
* *
*****************************************************************************/
#if @HELP_EXPM1
EXPM1
Purpose: Computes exp(x) - 1 for small x.
Syntax: EXPM1(x)
x - A scalar or series.
Returns: A scalar or series, the value of log(1 + x).
Example:
expm1(1e-17)
returns 1.000000E-17
exp(1e-17) - 1
returns 0.0
Example:
expm1(log1p(1e-17))
returns 1.000000E-17
exp(log(1 + 1e-17)) - 1
returns 0.0
Remarks:
For real values, EXPM1 is accurate for small x where
1 + x == 1 for double precision accuracy.
For small x, EXPM1(x) is approximately x, but EXP(x) - 1
is approximately 0 for double precision accuracy.
See LOG1P to compute LOG(1 + x) for small x, the inverse of
EXPM1.
See Also:
Exp
Log
Log1p
#endif
/* compute exp(x) - 1 for small x */
expm1(x)
{
local y, a, k, range, g_e8;
y = x;
a = abs(x);
range = a >= eps && a <= log(2);
if (any(range))
{
g_e8 = a > 1e-8;
k = find(range && g_e8);
y[k] = exp(x[k]) - 1;
/* Taylor expansion, more accurate in this range */
k = find(range && not(g_e8));
y[k] = (x[k] / 2 + 1) * x[k];
/* Newton step for solving log(1 + y) = x for y */
k = find(range);
y[k] -= (1 + y[k]) * (log1p(y[k]) - x[k]);
}
/* tiny */
k = find(a < eps);
y[k] = x[k];
/* negligible cancellation */
k = find(a > log(2));
y[k] = exp(x[k]) - 1;
return(y);
}