#include "mymath.h"

float
alog1p(float x)
{
    /*
     * (log1p)
     * Return alog(1 + x), taking care to avoid subtraction loss.
     *
     * This version uses a [3,3]-degree rational minimax polynomial
     * computed in Maple by
     *
     *     with(numapprox):
     *     Digits := 50:
     *     minimax(log(1+x)/x, x = -0.5..0.5, [3,3], 1, 'err');
     *     printf("%0.2e\n", err);
     *
     * The reported absolute error is 2.45e-08, below the IEEE 754
     * machine epsilon of 2**(-23) = 1.19e-07  This is the lowest
     * degree, and thus optimal, minimax polynomial whose error is below
     * that limit.
     * (24-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 ZERO = 0.0F;

    /* System generated locals */
    float 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)
    {
	ret_val = x * 
	    ( (((x * 0.0082862580412823251435257202370540692007126417294918F
		 + 0.33942388067339460599561720063252422038001227423002F)
		* x + 1.1457993412830483804452242822932061054397731762605F)
	       * x + 0.89528566772543246738887712811665813199451392473096F) /
	      (((x * 0.11981957345887679448770779971480950107963978021251F
		 + 0.83771450627164943928316301501161820258296653061808F)
		* x + 1.5934420741810454320614855954112896708163633216071F)
	       * x + 0.89528568671604382008960462312354772467712918367274F) );
    }
    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);
}
