#include "mymath.h"

float
alog1p(float x)
{
    /* (log1p) */
    /* Return alog(1 + x), taking care to avoid subtraction loss. */

    /* This version uses an alternate form of the Taylor series that */
    /* requires only about a quarter as many terms, and has only positive */
    /* terms. */
    /* (17-Jun-2002) */

    /* Initialized data */
    static float CUTLO = -0.5F;	/* CUTLO = -1/beta, for arbitrary base beta */
    static float CUTHI = 0.5F;	/* CUTHI = 1/beta, for arbitrary base beta */
    static float ONE = 1.0F;
    static float TWO = 2.0F;
    static float ZERO = 0.0F;

    /* System generated locals */
    float ret_val;

    /* Local variables */
    float
	term,
	sum,
	twonp1,
	z,
	zsq,
	zsqton;

    /* We handle the computation in three regions:
     *
     * x in [-Infinity, CUTLO):  log(1+x)
     * x in [CUTLO, CUTHI]:      alternate Taylor series
     * x in (CUTHI, Infinity]:   log(1+x)
     *
     * The central region suffers loss of ONE or more bits if the
     * simple formula is used.
     *
     * We also handle the cases of log1p(NaN) and log1p(0) specially,
     * so as to preserve NaNs, and the sign of ZERO.
     */

    if (x != x)
	ret_val = x;
    else if (x == ZERO)
	ret_val = x;
    else if (x < CUTLO)
	ret_val = LOG(ONE + x);
    else if (x <= CUTHI)
    {
	sum = ZERO;
	term = ONE;
	twonp1 = ONE;
	z = x / (TWO + x);
	zsq = z * z;
	zsqton = ONE;
	while ((sum + term) != sum)
	{
	    sum += term;
	    twonp1 += TWO;
	    zsqton *= zsq;
	    term = zsqton / twonp1;
	}
	ret_val = z * (sum + sum);
    }
    else
	ret_val = LOG(ONE + x);

    return (ret_val);
}


float
al1p10(float x)
{
    /* (log1p10) */
    /* Return alog10(1 + x), taking care to avoid subtraction loss. */
    /* (17-Jun-2002) */

    static float LOG10E = 0.43429448190325182765112891891660508229439700580366F;

    return (alog1p(x) * LOG10E);
}
