Exemple #1
0
float complex
catanhf(float complex z)
{
	float x, y, ax, ay, rx, ry;

	x = crealf(z);
	y = cimagf(z);
	ax = fabsf(x);
	ay = fabsf(y);

	if (y == 0 && ax <= 1)
		return (CMPLXF(atanhf(x), y));

	if (x == 0)
		return (CMPLXF(x, atanf(y)));

	if (isnan(x) || isnan(y)) {
		if (isinf(x))
			return (CMPLXF(copysignf(0, x), y + y));
		if (isinf(y))
			return (CMPLXF(copysignf(0, x),
			    copysignf(pio2_hi + pio2_lo, y)));
		return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
	}

	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
		return (CMPLXF(real_part_reciprocal(x, y),
		    copysignf(pio2_hi + pio2_lo, y)));

	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
		raise_inexact();
		return (z);
	}

	if (ax == 1 && ay < FLT_EPSILON)
		rx = (m_ln2 - logf(ay)) / 2;
	else
		rx = log1pf(4 * ax / sum_squares(ax - 1, ay)) / 4;

	if (ax == 1)
		ry = atan2f(2, -ay) / 2;
	else if (ay < FLT_EPSILON)
		ry = atan2f(2 * ay, (1 - ax) * (1 + ax)) / 2;
	else
		ry = atan2f(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;

	return (CMPLXF(copysignf(rx, x), copysignf(ry, y)));
}
Exemple #2
0
long double complex
catanhl(long double complex z)
{
	long double x, y, ax, ay, rx, ry;

	x = creall(z);
	y = cimagl(z);
	ax = fabsl(x);
	ay = fabsl(y);

	if (y == 0 && ax <= 1)
		return (CMPLXL(atanhl(x), y));

	if (x == 0)
		return (CMPLXL(x, atanl(y)));

	if (isnan(x) || isnan(y)) {
		if (isinf(x))
			return (CMPLXL(copysignl(0, x), y + y));
		if (isinf(y))
			return (CMPLXL(copysignl(0, x),
			    copysignl(pio2_hi + pio2_lo, y)));
		return (CMPLXL(nan_mix(x, y), nan_mix(x, y)));
	}

	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
		return (CMPLXL(real_part_reciprocal(x, y),
		    copysignl(pio2_hi + pio2_lo, y)));

	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
		raise_inexact();
		return (z);
	}

	if (ax == 1 && ay < LDBL_EPSILON)
		rx = (m_ln2 - logl(ay)) / 2;
	else
		rx = log1pl(4 * ax / sum_squares(ax - 1, ay)) / 4;

	if (ax == 1)
		ry = atan2l(2, -ay) / 2;
	else if (ay < LDBL_EPSILON)
		ry = atan2l(2 * ay, (1 - ax) * (1 + ax)) / 2;
	else
		ry = atan2l(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;

	return (CMPLXL(copysignl(rx, x), copysignl(ry, y)));
}
Exemple #3
0
/*
 * catanh(z) = log((1+z)/(1-z)) / 2
 *           = log1p(4*x / |z-1|^2) / 4
 *             + I * atan2(2*y, (1-x)*(1+x)-y*y) / 2
 *
 * catanh(z) = z + O(z^3)   as z -> 0
 *
 * catanh(z) = 1/z + sign(y)*I*PI/2 + O(1/z^3)   as z -> infinity
 * The above formula works for the real part as well, because
 * Re(catanh(z)) = x/|z|^2 + O(x/z^4)
 *    as z -> infinity, uniformly in x
 */
double complex
catanh(double complex z)
{
	double x, y, ax, ay, rx, ry;

	x = creal(z);
	y = cimag(z);
	ax = fabs(x);
	ay = fabs(y);

	/* This helps handle many cases. */
	if (y == 0 && ax <= 1)
		return (CMPLX(atanh(x), y));

	/* To ensure the same accuracy as atan(), and to filter out z = 0. */
	if (x == 0)
		return (CMPLX(x, atan(y)));

	if (isnan(x) || isnan(y)) {
		/* catanh(+-Inf + I*NaN) = +-0 + I*NaN */
		if (isinf(x))
			return (CMPLX(copysign(0, x), y + y));
		/* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */
		if (isinf(y))
			return (CMPLX(copysign(0, x),
			    copysign(pio2_hi + pio2_lo, y)));
		/*
		 * All other cases involving NaN return NaN + I*NaN.
		 * C99 leaves it optional whether to raise invalid if one of
		 * the arguments is not NaN, so we opt not to raise it.
		 */
		return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
	}

	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
		return (CMPLX(real_part_reciprocal(x, y),
		    copysign(pio2_hi + pio2_lo, y)));

	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
		/*
		 * z = 0 was filtered out above.  All other cases must raise
		 * inexact, but this is the only only that needs to do it
		 * explicitly.
		 */
		raise_inexact();
		return (z);
	}

	if (ax == 1 && ay < DBL_EPSILON)
		rx = (m_ln2 - log(ay)) / 2;
	else
		rx = log1p(4 * ax / sum_squares(ax - 1, ay)) / 4;

	if (ax == 1)
		ry = atan2(2, -ay) / 2;
	else if (ay < DBL_EPSILON)
		ry = atan2(2 * ay, (1 - ax) * (1 + ax)) / 2;
	else
		ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;

	return (CMPLX(copysign(rx, x), copysign(ry, y)));
}