예제 #1
0
static inline long double
real_part_reciprocal(long double x, long double y)
{
	long double scale;
	uint16_t hx, hy;
	int16_t ix, iy;

	GET_LDBL_EXPSIGN(hx, x);
	ix = hx & 0x7fff;
	GET_LDBL_EXPSIGN(hy, y);
	iy = hy & 0x7fff;
#define	BIAS	(LDBL_MAX_EXP - 1)
#define	CUTOFF	(LDBL_MANT_DIG / 2 + 1)
	if (ix - iy >= CUTOFF || isinf(x))
		return (1 / x);
	if (iy - ix >= CUTOFF)
		return (x / y / y);
	if (ix <= BIAS + LDBL_MAX_EXP / 2 - CUTOFF)
		return (x / (x * x + y * y));
	scale = 1;
	SET_LDBL_EXPSIGN(scale, 0x7fff - ix);
	x *= scale;
	y *= scale;
	return (x / (x * x + y * y) * scale);
}
예제 #2
0
long double
sinhl(long double x)
{
	long double hi,lo,x2,x4;
	double dx2,s;
	int16_t ix,jx;

	GET_LDBL_EXPSIGN(jx,x);
	ix = jx&0x7fff;

    /* x is INF or NaN */
	if(ix>=0x7fff) return x+x;

	ENTERI();

	s = 1;
	if (jx<0) s = -1;

    /* |x| < 64, return x, s(x), or accurate s*(exp(|x|)/2-1/exp(|x|)/2) */
	if (ix<0x4005) {		/* |x|<64 */
	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x|<TINY */
		if(shuge+x>1) RETURNI(x);  /* sinh(tiny) = tiny with inexact */
	    if (ix<0x3fff) {		/* |x|<1 */
		x2 = x*x;
#if LDBL_MANT_DIG == 64
		x4 = x2*x2;
		RETURNI(((S17*x2 + S15)*x4 + (S13*x2 + S11))*(x2*x*x4*x4) +
		    ((S9*x2 + S7)*x2 + S5)*(x2*x*x2) + S3*(x2*x) + x);
#elif LDBL_MANT_DIG == 113
		dx2 = x2;
		RETURNI(((((((((((S25*dx2 + S23)*dx2 +
		    S21)*x2 + S19)*x2 +
		    S17)*x2 + S15)*x2 + S13)*x2 + S11)*x2 + S9)*x2 + S7)*x2 +
		    S5)* (x2*x*x2) +
		    S3*(x2*x) + x);
#endif
	    }
	    k_hexpl(fabsl(x), &hi, &lo);
	    RETURNI(s*(lo - 0.25/(hi + lo) + hi));
	}

    /* |x| in [64, o_threshold], return correctly-overflowing s*exp(|x|)/2 */
	if (fabsl(x) <= o_threshold)
	    RETURNI(s*hexpl(fabsl(x)));

    /* |x| > o_threshold, sinh(x) overflow */
	return x*shuge;
}
예제 #3
0
long double
coshl(long double x)
{
	long double hi,lo,x2,x4;
#if LDBL_MANT_DIG == 113
	double dx2;
#endif
	uint16_t ix;

	GET_LDBL_EXPSIGN(ix,x);
	ix &= 0x7fff;

    /* x is INF or NaN */
	if(ix>=0x7fff) return x*x;

	ENTERI();

    /* |x| < 1, return 1 or c(x) */
	if(ix<0x3fff) {
	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x| < TINY */
		RETURNI(1+tiny);	/* cosh(tiny) = 1(+) with inexact */
	    x2 = x*x;
#if LDBL_MANT_DIG == 64
	    x4 = x2*x2;
	    RETURNI(((C16*x2 + C14)*x4 + (C12*x2 + C10))*(x4*x4*x2) +
		((C8*x2 + C6)*x2 + C4)*x4 + C2*x2 + 1);
#elif LDBL_MANT_DIG == 113
	    dx2 = x2;
	    RETURNI((((((((((((C26*dx2 + C24)*dx2 + C22)*dx2 +
		C20)*x2 + C18)*x2 +
		C16)*x2 + C14)*x2 + C12)*x2 + C10)*x2 + C8)*x2 + C6)*x2 +
		C4)*(x2*x2) + C2*x2 + 1);
#endif
	}

    /* |x| in [1, 64), return accurate exp(|x|)/2+1/exp(|x|)/2 */
	if (ix < 0x4005) {
	    k_hexpl(fabsl(x), &hi, &lo);
	    RETURNI(lo + 0.25/(hi + lo) + hi);
	}

    /* |x| in [64, o_threshold], return correctly-overflowing exp(|x|)/2 */
	if (fabsl(x) <= o_threshold)
	    RETURNI(hexpl(fabsl(x)));

    /* |x| > o_threshold, cosh(x) overflow */
	RETURNI(huge*huge);
}
예제 #4
0
long double
atanhl(long double x)
{
	long double t;
	uint16_t hx, ix;

	ENTERI();
	GET_LDBL_EXPSIGN(hx, x);
	ix = hx & 0x7fff;
	if (ix >= 0x3fff)		/* |x| >= 1, or NaN or misnormal */
	    RETURNI(fabsl(x) == 1 ? x / zero : (x - x) / (x - x));
	if (ix < BIAS + EXP_TINY && (huge + x) > zero)
	    RETURNI(x);			/* x is tiny */
	SET_LDBL_EXPSIGN(x, ix);
	if (ix < 0x3ffe) {		/* |x| < 0.5, or misnormal */
	    t = x+x;
	    t = 0.5*log1pl(t+t*x/(one-x));
	} else 
	    t = 0.5*log1pl((x+x)/(one-x));
	RETURNI((hx & 0x8000) == 0 ? t : -t);
}
예제 #5
0
long double
roundl(long double x)
{
	long double t;
	uint16_t hx;

	GET_LDBL_EXPSIGN(hx, x);
	if ((hx & 0x7fff) == 0x7fff)
		return (x + x);

	ENTERI();

	if (!(hx & 0x8000)) {
		t = floorl(x);
		if (t - x <= -0.5L)
			t += 1;
		RETURNI(t);
	} else {
		t = floorl(-x);
		if (t + x <= -0.5L)
			t += 1;
		RETURNI(-t);
	}
}
예제 #6
0
long double
asinhl(long double x)
{
	long double t, w;
	uint16_t hx, ix;

	ENTERI();
	GET_LDBL_EXPSIGN(hx, x);
	ix = hx & 0x7fff;
	if (ix >= 0x7fff) RETURNI(x+x);	/* x is inf, NaN or misnormal */
	if (ix < BIAS + EXP_TINY) {	/* |x| < TINY, or misnormal */
	    if (huge + x > one) RETURNI(x);	/* return x inexact except 0 */
	}
	if (ix >= BIAS + EXP_LARGE) {	/* |x| >= LARGE, or misnormal */
	    w = logl(fabsl(x))+ln2;
	} else if (ix >= 0x4000) {	/* LARGE > |x| >= 2.0, or misnormal */
	    t = fabsl(x);
	    w = logl(2.0*t+one/(sqrtl(x*x+one)+t));
	} else {		/* 2.0 > |x| >= TINY, or misnormal */
	    t = x*x;
	    w =log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
	}
	RETURNI((hx & 0x8000) == 0 ? w : -w);
}
예제 #7
0
파일: s_tanhl.c 프로젝트: coyizumi/cs111
long double
tanhl(long double x)
{
	long double hi,lo,s,x2,x4,z;
	double dx2;
	int16_t jx,ix;

	GET_LDBL_EXPSIGN(jx,x);
	ix = jx&0x7fff;

    /* x is INF or NaN */
	if(ix>=0x7fff) {
	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
	    else       return one/x-one;    /* tanh(NaN) = NaN */
	}

	ENTERI();

    /* |x| < 40 */
	if (ix < 0x4004 || fabsl(x) < 40) {	/* |x|<40 */
	    if (__predict_false(ix<BIAS-(LDBL_MANT_DIG+1)/2)) {	/* |x|<TINY */
		/* tanh(+-0) = +0; tanh(tiny) = tiny(-+) with inexact: */
		return (x == 0 ? x : (0x1p200 * x - x) * 0x1p-200);
	    }
	    if (ix<0x3ffd) {		/* |x|<0.25 */
		x2 = x*x;
#if LDBL_MANT_DIG == 64
		x4 = x2*x2;
		RETURNI(((T19*x2 + T17)*x4 + (T15*x2 + T13))*(x2*x*x2*x4*x4) +
		    ((T11*x2 + T9)*x4 + (T7*x2 + T5))*(x2*x*x2) +
		    T3*(x2*x) + x);
#elif LDBL_MANT_DIG == 113
		dx2 = x2;
#if 0
		RETURNI(((((((((((((((T33*dx2 + T31)*dx2 + T29)*dx2 + T27)*dx2 +
		    T25)*x2 + T23)*x2 + T21)*x2 + T19)*x2 + T17)*x2 +
		    T15)*x2 + T13)*x2 + T11)*x2 + T9)*x2 + T7)*x2 + T5)*
		    (x2*x*x2) +
		    T3*(x2*x) + x);
#else
		long double q = ((((((((((((((T33*dx2 + T31)*dx2 + T29)*dx2 + T27)*dx2 +
		    T25)*x2 + T23)*x2 + T21)*x2 + T19)*x2 + T17)*x2 +
		    T15)*x2 + T13)*x2 + T11)*x2 + T9)*x2 + T7)*x2 + T5)*
		    (x2*x*x2);
		RETURNI(q + T3*(x2*x) + x);
#endif
#endif
	    }
	    k_hexpl(2*fabsl(x), &hi, &lo);
	    if (ix<0x4001 && fabsl(x) < 1.5)	/* |x|<1.5 */
		z = divl(hi, lo, -0.5, hi, lo, 0.5);
	    else
		z = one - one/(lo+0.5+hi);
    /* |x| >= 40, return +-1 */
	} else {
	    z = one - tiny;		/* raise inexact flag */
	}
	s = 1;
	if (jx<0) s = -1;
	RETURNI(s*z);
}
예제 #8
0
long double complex
clogl(long double complex z)
{
	long double ax, ax2h, ax2l, axh, axl, ay, ay2h, ay2l, ayh, ayl;
	long double sh, sl, t;
	long double x, y, v;
	uint16_t hax, hay;
	int kx, ky;

	ENTERIT(long double complex);

	x = creall(z);
	y = cimagl(z);
	v = atan2l(y, x);

	ax = fabsl(x);
	ay = fabsl(y);
	if (ax < ay) {
		t = ax;
		ax = ay;
		ay = t;
	}

	GET_LDBL_EXPSIGN(hax, ax);
	kx = hax - 16383;
	GET_LDBL_EXPSIGN(hay, ay);
	ky = hay - 16383;

	/* Handle NaNs and Infs using the general formula. */
	if (kx == MAX_EXP || ky == MAX_EXP)
		RETURNI(CMPLXL(logl(hypotl(x, y)), v));

	/* Avoid spurious underflow, and reduce inaccuracies when ax is 1. */
	if (ax == 1) {
		if (ky < (MIN_EXP - 1) / 2)
			RETURNI(CMPLXL((ay / 2) * ay, v));
		RETURNI(CMPLXL(log1pl(ay * ay) / 2, v));
	}

	/* Avoid underflow when ax is not small.  Also handle zero args. */
	if (kx - ky > MANT_DIG || ay == 0)
		RETURNI(CMPLXL(logl(ax), v));

	/* Avoid overflow. */
	if (kx >= MAX_EXP - 1)
		RETURNI(CMPLXL(logl(hypotl(x * 0x1p-16382L, y * 0x1p-16382L)) +
		    (MAX_EXP - 2) * ln2l_lo + (MAX_EXP - 2) * ln2_hi, v));
	if (kx >= (MAX_EXP - 1) / 2)
		RETURNI(CMPLXL(logl(hypotl(x, y)), v));

	/* Reduce inaccuracies and avoid underflow when ax is denormal. */
	if (kx <= MIN_EXP - 2)
		RETURNI(CMPLXL(logl(hypotl(x * 0x1p16383L, y * 0x1p16383L)) +
		    (MIN_EXP - 2) * ln2l_lo + (MIN_EXP - 2) * ln2_hi, v));

	/* Avoid remaining underflows (when ax is small but not denormal). */
	if (ky < (MIN_EXP - 1) / 2 + MANT_DIG)
		RETURNI(CMPLXL(logl(hypotl(x, y)), v));

	/* Calculate ax*ax and ay*ay exactly using Dekker's algorithm. */
	t = (long double)(ax * (MULT_REDUX + 1));
	axh = (long double)(ax - t) + t;
	axl = ax - axh;
	ax2h = ax * ax;
	ax2l = axh * axh - ax2h + 2 * axh * axl + axl * axl;
	t = (long double)(ay * (MULT_REDUX + 1));
	ayh = (long double)(ay - t) + t;
	ayl = ay - ayh;
	ay2h = ay * ay;
	ay2l = ayh * ayh - ay2h + 2 * ayh * ayl + ayl * ayl;

	/*
	 * When log(|z|) is far from 1, accuracy in calculating the sum
	 * of the squares is not very important since log() reduces
	 * inaccuracies.  We depended on this to use the general
	 * formula when log(|z|) is very far from 1.  When log(|z|) is
	 * moderately far from 1, we go through the extra-precision
	 * calculations to reduce branches and gain a little accuracy.
	 *
	 * When |z| is near 1, we subtract 1 and use log1p() and don't
	 * leave it to log() to subtract 1, since we gain at least 1 bit
	 * of accuracy in this way.
	 *
	 * When |z| is very near 1, subtracting 1 can cancel almost
	 * 3*MANT_DIG bits.  We arrange that subtracting 1 is exact in
	 * doubled precision, and then do the rest of the calculation
	 * in sloppy doubled precision.  Although large cancellations
	 * often lose lots of accuracy, here the final result is exact
	 * in doubled precision if the large calculation occurs (because
	 * then it is exact in tripled precision and the cancellation
	 * removes enough bits to fit in doubled precision).  Thus the
	 * result is accurate in sloppy doubled precision, and the only
	 * significant loss of accuracy is when it is summed and passed
	 * to log1p().
	 */
	sh = ax2h;
	sl = ay2h;
	_2sumF(sh, sl);
	if (sh < 0.5 || sh >= 3)
		RETURNI(CMPLXL(logl(ay2l + ax2l + sl + sh) / 2, v));
	sh -= 1;
	_2sum(sh, sl);
	_2sum(ax2l, ay2l);
	/* Briggs-Kahan algorithm (except we discard the final low term): */
	_2sum(sh, ax2l);
	_2sum(sl, ay2l);
	t = ax2l + sl;
	_2sumF(sh, t);
	RETURNI(CMPLXL(log1pl(ay2l + t + sh) / 2, v));
}