From 10e4bd3780050e75b72aac5d85c31816419bb17d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Apr 2018 15:05:22 -0400 Subject: [PATCH] fix incorrect results for catan with some inputs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit the catan implementation from OpenBSD includes a FIXME-annotated "overflow" branch that produces a meaningless and incorrect large-magnitude result. it was reachable via three paths, corresponding to gotos removed by this commit, in order: 1. pure imaginary argument with imaginary component greater than 1 in magnitude. this case does not seem at all exceptional and is handled (at least with the quality currently expected from our complex math functions) by the existing non-exceptional code path. 2. arguments on the unit circle, including the pure-real argument 1.0. these are not exceptional except for ±i, which should produce results with infinite imaginary component and which lead to computation of atan2(±0,0) in the existing non-exceptional code path. such calls to atan2() however are well-defined by POSIX. 3. the specific argument +i. this route should be unreachable due to the above (2), but subtle rounding effects might have made it possible in rare cases. continuing on the non-exceptional code path in this case would lead to computing the (real) log of an infinite argument, then producing a NAN when multiplying it by I. for now, remove the exceptional code paths entirely. replace the multiplication by I with construction of a complex number using the CMPLX macro so that the NAN issue (3) prevented cannot arise. with these changes, catan should give reasonably correct results for real arguments, and should no longer give completely-wrong results for pure-imaginary arguments outside the interval (-i,+i). --- src/complex/catan.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/complex/catan.c b/src/complex/catan.c index 39ce6cf2..7dc2afeb 100644 --- a/src/complex/catan.c +++ b/src/complex/catan.c @@ -91,29 +91,17 @@ double complex catan(double complex z) x = creal(z); y = cimag(z); - if (x == 0.0 && y > 1.0) - goto ovrf; - x2 = x * x; a = 1.0 - x2 - (y * y); - if (a == 0.0) - goto ovrf; t = 0.5 * atan2(2.0 * x, a); w = _redupi(t); t = y - 1.0; a = x2 + (t * t); - if (a == 0.0) - goto ovrf; t = y + 1.0; a = (x2 + t * t)/a; - w = w + (0.25 * log(a)) * I; - return w; - -ovrf: - // FIXME - w = MAXNUM + MAXNUM * I; + w = CMPLX(w, 0.25 * log(a)); return w; } -- 2.25.1