#include "mymath.h"

double
dlog1p(double x)
{
    /*
     * (log1p)
     * Return dlog(1 + x), taking care to avoid subtraction loss.
     *
     * This version uses a [7,6]-degree rational minimax polynomial
     * computed in Maple by
     *
     *     with(numapprox):
     *     Digits := 50:
     *     minimax((ln(1+x)-x)/x^2, x = -0.5..0.5, [7,6], 1, 'err');
     *     printf("%0.2e\n", err);
     *
     * The reported absolute error is 7.17e-17, below the IEEE 754
     * machine epsilon of 2**(-52) = 2.22e-16. This is the lowest
     * degree, and thus optimal, minimax polynomial whose error is below
     * that limit.
     * (24-Jun-2002)
     */

    /* Initialized data */

    static double CUTLO = -0.5;	/* CUTLO = -1/beta, for arbitrary base beta */
    static double CUTHI = 0.5;	/* CUTHI = 1/beta, for arbitrary base beta */
    static double ONE = 1.0;
    static double ZERO = 0.0;

    /* System generated locals */
    double ret_val;

    /*
     *     We handle the computation in three regions:
     *
     *     x in [-Infinity, CUTLO):  log(1+x)
     *     x in [CUTLO, CUTHI]:      minimax rational polynomial
     *     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)
    {					/* Error = 1.53e-16 */
	ret_val = x +
	    (x * x *
	     (
	      ( -2.8914570958276356e-01 +
	       ( -8.8388057507274367e-01 +
		( -1.0247798215469895e+00 +
		 ( -5.5577579361179802e-01 +
		  ( -1.3834683248688421e-01 +
		   ( -1.2342893701985236e-02 +
		    ( -2.3225275641316998e-05 +
		     (  8.3095603786418285e-07
		      ) * x) * x) * x) * x) * x) * x) * x)
	      /
	      (  5.7829141916552716e-01 +
	       (  2.1532887629225038e+00 +
		(  3.1959397754595289e+00 +
		 (  2.3968502904017205e+00 +
		  (  9.4517566962711295e-01 +
		   (  1.8221686425529235e-01 +
		    (  1.3015888925957095e-02
		     ) * x) * x) * x) * x) * x) * x) ) );
    }
    else
	ret_val = LOG(ONE + x);

    return (ret_val);
}


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

    static double LOG10E = 0.43429448190325182765112891891660508229439700580366;

    return (dlog1p(x) * LOG10E);
}
