Ejemplo n.º 1
0
long double
cbrtl(long double x) {
	long double s, t, r, w, y;
	double dx, dy;
	int *py = (int *) &dy;
	int n, m, m3, sx;

	if (!finitel(x))
		return (x + x);
	if (iszerol(x))
		return (x);
	sx = signbitl(x);
	x = fabsl(x);
	n = ilogbl(x);
	m = n / 3;
	m3 = m + m + m;
	y = scalbnl(x, -m3);
	dx = (double) y;
	dy = cbrt(dx);
	py[1 - n0] += 2;
	if (py[1 - n0] == 0)
		py[n0] += 1;

	/* one step newton iteration to 113 bits with error < 0.667ulps */
	t = (long double) dy;
	t = scalbnl(t, m);
	s = t * t;
	r = x / s;
	w = t + t;
	r = (r - t) / (w + r);
	t += t * r;

	return (sx == 0 ? t : -t);
}
Ejemplo n.º 2
0
ldcomplex
catanl(ldcomplex z) {
	ldcomplex ans;
	long double x, y, t1, ax, ay, t;
	int hx, hy, ix, iy;

	x = LD_RE(z);
	y = LD_IM(z);
	ax = fabsl(x);
	ay = fabsl(y);
	hx = HI_XWORD(x);
	hy = HI_XWORD(y);
	ix = hx & 0x7fffffff;
	iy = hy & 0x7fffffff;

	/* x is inf or NaN */
	if (ix >= 0x7fff0000) {
		if (isinfl(x)) {
			LD_RE(ans) = pi_2;
			LD_IM(ans) = zero;
		} else {
			LD_RE(ans) = x + x;
			if (iszerol(y) || (isinfl(y)))
				LD_IM(ans) = zero;
			else
				LD_IM(ans) = (fabsl(y) - ay) / (fabsl(y) - ay);
		}
	} else if (iy >= 0x7fff0000) {
		/* y is inf or NaN */
		if (isinfl(y)) {
			LD_RE(ans) = pi_2;
			LD_IM(ans) = zero;
		} else {
			LD_RE(ans) = (fabsl(x) - ax) / (fabsl(x) - ax);
			LD_IM(ans) = y;
		}
	} else if (iszerol(x)) {
		/* INDENT OFF */
		/*
		 * x = 0
		 *      1                            1
		 * A = --- * atan2(2x, 1-x*x-y*y) = --- atan2(0,1-|y|)
		 *      2                            2
		 *
		 *     1     [ (y+1)*(y+1) ]   1          2      1         2y
		 * B = - log [ ----------- ] = - log (1+ ---) or - log(1+ ----)
		 *     4     [ (y-1)*(y-1) ]   2         y-1     2         1-y
		 */
		/* INDENT ON */
		t = one - ay;
		if (ay == one) {
			/* y=1: catan(0,1)=(0,+inf) with 1/0 signal */
			LD_IM(ans) = ay / ax;
			LD_RE(ans) = zero;
		} else if (ay > one) {	/* y>1 */
			LD_IM(ans) = half * log1pl(two / (-t));
			LD_RE(ans) = pi_2;
		} else {		/* y<1 */
			LD_IM(ans) = half * log1pl((ay + ay) / t);
			LD_RE(ans) = zero;
		}
	} else if (ay < E * (one + ax)) {
		/* INDENT OFF */
		/*
		 * Tiny y (relative to 1+|x|)
		 *     |y| < E*(1+|x|)
		 * where E=2**-29, -35, -60 for double, extended, quad precision
		 *
		 *     1                         [x<=1:   atan(x)
		 * A = - * atan2(2x,1-x*x-y*y) ~ [      1                 1+x
		 *     2                         [x>=1: - atan2(2,(1-x)*(-----))
		 *                                      2                  x
		 *
		 *                               y/x
		 * B ~ t*(1-2t), where t = ----------------- is tiny
		 *                         x + (y-1)*(y-1)/x
		 *
		 *                           y
		 * (when x < 2**-60, t = ----------- )
		 *                       (y-1)*(y-1)
		 */
		/* INDENT ON */
		if (ay == zero)
			LD_IM(ans) = ay;
		else {
			t1 = ay - one;
			if (ix < 0x3fc30000)
				t = ay / (t1 * t1);
			else if (ix > 0x403b0000)
				t = (ay / ax) / ax;
			else
				t = ay / (ax * ax + t1 * t1);
			LD_IM(ans) = t * (one - two * t);
		}
		if (ix < 0x3fff0000)
			LD_RE(ans) = atanl(ax);
		else
			LD_RE(ans) = half * atan2l(two, (one - ax) * (one +
				one / ax));

	} else if (ay > Einv * (one + ax)) {
		/* INDENT OFF */
		/*
		 * Huge y relative to 1+|x|
		 *     |y| > Einv*(1+|x|), where Einv~2**(prec/2+3),
		 *      1
		 * A ~ --- * atan2(2x, -y*y) ~ pi/2
		 *      2
		 *                               y
		 * B ~ t*(1-2t), where t = --------------- is tiny
		 *                          (y-1)*(y-1)
		 */
		/* INDENT ON */
		LD_RE(ans) = pi_2;
		t = (ay / (ay - one)) / (ay - one);
		LD_IM(ans) = t * (one - (t + t));
	} else if (ay == one) {
		/* INDENT OFF */
		/*
		 * y=1
		 *     1                      1
		 * A = - * atan2(2x, -x*x) = --- atan2(2,-x)
		 *     2                      2
		 *
		 *     1     [ x*x+4]   1          4     [ 0.5(log2-logx) if
		 * B = - log [ -----] = - log (1+ ---) = [ |x|<E, else 0.25*
		 *     4     [  x*x ]   4         x*x    [ log1p((2/x)*(2/x))
		 */
		/* INDENT ON */
		LD_RE(ans) = half * atan2l(two, -ax);
		if (ax < E)
			LD_IM(ans) = half * (ln2 - logl(ax));
		else {
			t = two / ax;
			LD_IM(ans) = 0.25L * log1pl(t * t);
		}
	} else if (ax > Einv * Einv) {
		/* INDENT OFF */
		/*
		 * Huge x:
		 * when |x| > 1/E^2,
		 *      1                           pi
		 * A ~ --- * atan2(2x, -x*x-y*y) ~ ---
		 *      2                           2
		 *                               y                 y/x
		 * B ~ t*(1-2t), where t = --------------- = (-------------- )/x
		 *                         x*x+(y-1)*(y-1)     1+((y-1)/x)^2
		 */
		/* INDENT ON */
		LD_RE(ans) = pi_2;
		t = ((ay / ax) / (one + ((ay - one) / ax) * ((ay - one) /
			ax))) / ax;
		LD_IM(ans) = t * (one - (t + t));
	} else if (ax < E * E * E * E) {
		/* INDENT OFF */
		/*
		 * Tiny x:
		 * when |x| < E^4,  (note that y != 1)
		 *      1                            1
		 * A = --- * atan2(2x, 1-x*x-y*y) ~ --- * atan2(2x,1-y*y)
		 *      2                            2
		 *
		 *     1     [ (y+1)*(y+1) ]   1          2      1         2y
		 * B = - log [ ----------- ] = - log (1+ ---) or - log(1+ ----)
		 *     4     [ (y-1)*(y-1) ]   2         y-1     2         1-y
		 */
		/* INDENT ON */
		LD_RE(ans) = half * atan2l(ax + ax, (one - ay) * (one + ay));
		if (ay > one)	/* y>1 */
			LD_IM(ans) = half * log1pl(two / (ay - one));
		else		/* y<1 */
			LD_IM(ans) = half * log1pl((ay + ay) / (one - ay));
	} else {
		/* INDENT OFF */
		/*
		 * normal x,y
		 *      1
		 * A = --- * atan2(2x, 1-x*x-y*y)
		 *      2
		 *
		 *     1     [ x*x+(y+1)*(y+1) ]   1               4y
		 * B = - log [ --------------- ] = - log (1+ -----------------)
		 *     4     [ x*x+(y-1)*(y-1) ]   4         x*x + (y-1)*(y-1)
		 */
		/* INDENT ON */
		t = one - ay;
		if (iy >= 0x3ffe0000 && iy < 0x40000000) {
			/* y close to 1 */
			LD_RE(ans) = half * (atan2l((ax + ax), (t * (one +
				ay) - ax * ax)));
		} else if (ix >= 0x3ffe0000 && ix < 0x40000000) {
			/* x close to 1 */
			LD_RE(ans) = half * atan2l((ax + ax), ((one - ax) *
				(one + ax) - ay * ay));
		} else
			LD_RE(ans) = half * atan2l((ax + ax), ((one - ax *
				ax) - ay * ay));
		LD_IM(ans) = 0.25L * log1pl((4.0L * ay) / (ax * ax + t * t));
	}
	if (hx < 0)
		LD_RE(ans) = -LD_RE(ans);
	if (hy < 0)
		LD_IM(ans) = -LD_IM(ans);
	return (ans);
}