#include "mymath.h"

long double
qlog1p(long double x)
{
    /*
     * (log1p)
     * Return qlog(1 + x), taking care to avoid subtraction loss.
     *
     * This version incorporates run-time precomputation of a table
     * of reciprocals to replace division by multiplication in the
     * Taylor series computation.
     * (17-Jun-2002)
     */

    /* Initialized data */

    static int first = 1;
    static long double CUTLO = -0.5L;	/* CUTLO = -1/beta, for arbitrary base beta */
    static long double CUTHI = 0.5L;	/* CUTHI = 1/beta, for arbitrary base beta */
    static long double ONE = 1.0L;
    static long double ZERO = 0.0L;
#define MAXN_ 117
    static int MAXN = MAXN_;
    static long double xninv[MAXN_];

    /* System generated locals */
    long double ret_val;

    /* Local variables */
    int n;
    long double sum,
	term,
	xtons;

    /* The maximum number of Taylor series terms (20, 48, 59, 107) is */
    /* known in advance, but we compute 10 more reciprocals for safety. */

    if (first == 1)
    {
	for (n = 1; n <= MAXN; ++n)
	    xninv[n - 1] = ONE / (long double)n;
	first = 0;
    }

    /*
     *     We handle the computation in three regions:
     *
     *     x in [-Infinity, CUTLO):  log(1+x)
     *     x in [CUTLO, CUTHI]:      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)
    {
	term = x;
	sum = ZERO;
	n = 1;
	xtons = x;
	while ((sum + term) != sum)
	{
	    sum += term;
	    xtons = -xtons * x;
	    term = xtons * xninv[n];
	    ++n;
	}
	ret_val = sum;
    }
    else
	ret_val = LOG(ONE + x);

    return (ret_val);
}


long double
ql1p10(long double x)
{
    /* (log1p10) */
    /* Return qlog10(1 + x), taking care to avoid subtraction loss. */
    /* (17-Jun-2002) */

    static long double LOG10E = 0.43429448190325182765112891891660508229439700580366L;

    return (qlog1p(x) * LOG10E);
}
