From d0419dbfbd19cb01398d43895a679c0bcb961070 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 31 Jul 2012 14:21:19 +0000 Subject: Improve clog, clog10 handling of values with real or imaginary part slightly above 1 (bug 13629). --- math/libm-test.inc | 22 ++++++++++++++++++++++ math/s_clog.c | 7 +++++++ math/s_clog10.c | 7 +++++++ math/s_clog10f.c | 7 +++++++ math/s_clog10l.c | 14 ++++++++++++++ math/s_clogf.c | 7 +++++++ math/s_clogl.c | 14 ++++++++++++++ 7 files changed, 78 insertions(+) (limited to 'math') diff --git a/math/libm-test.inc b/math/libm-test.inc index c2fb50cec2..0f64ea4971 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -2484,6 +2484,17 @@ clog_test (void) TEST_c_c (clog, 0x1p-8192L, 1.0L, 4.202628928890116882828347271652190753248e-4933L, 1.570796326794896619231321691639751442099L, UNDERFLOW_EXCEPTION); #endif + TEST_c_c (clog, 0x1.000566p0L, 0x1.234p-10L, 8.298731898331237038231468223024422855654e-5L, 1.110938609507128729312743251313024793990e-3L); + TEST_c_c (clog, 0x1.000566p0L, 0x1.234p-100L, 8.237022655933121125560939513260027133767e-5L, 8.974094312218060110948251664314290484113e-31L); +#ifndef TEST_FLOAT + TEST_c_c (clog, -0x1.0000000123456p0L, 0x1.2345678p-30L, 2.649094282537168795982991778475646793277e-10L, 3.141592652530155111500161671113150737892L); + TEST_c_c (clog, -0x1.0000000123456p0L, 0x1.2345678p-1000L, 2.649094276923003995420209214900915462737e-10L, 3.141592653589793238462643383279502884197L); +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_c_c (clog, 0x1.00000000000000123456789abcp0L, 0x1.23456789p-60L, 9.868649107778739757272772275265050767867e-19L, 9.868649106423871142816660980898339912137e-19L); + TEST_c_c (clog, 0x1.00000000000000123456789abcp0L, 0x1.23456789p-1000L, 9.868649107778739752403260515979017248596e-19L, 1.061846605795612822522063052130030717368e-301L); +#endif + END (clog, complex); } @@ -2633,6 +2644,17 @@ clog10_test (void) TEST_c_c (clog10, 0x1p-8191L, 1.0L, 7.300714213215805914467117112656302312931e-4933L, 6.821881769209206737428918127156778851051e-1L, UNDERFLOW_EXCEPTION); #endif + TEST_c_c (clog10, 0x1.000566p0L, 0x1.234p-10L, 3.604093470239754109961125085078190708674e-5L, 4.824745078422174667425851670822596859720e-4L); + TEST_c_c (clog10, 0x1.000566p0L, 0x1.234p-100L, 3.577293486783822178310971763308187385546e-5L, 3.897399639875661463735636919790792140598e-31L); +#ifndef TEST_FLOAT + TEST_c_c (clog10, -0x1.0000000123456p0L, 0x1.2345678p-30L, 1.150487028947346337782682105935961875822e-10L, 1.364376353381646356131680448946397884147L); + TEST_c_c (clog10, -0x1.0000000123456p0L, 0x1.2345678p-1000L, 1.150487026509145544402795327729455391948e-10L, 1.364376353841841347485783625431355770210L); +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_c_c (clog10, 0x1.00000000000000123456789abcp0L, 0x1.23456789p-60L, 4.285899851347756188767674032946882584784e-19L, 4.285899850759344225805480528847018395861e-19L); + TEST_c_c (clog10, 0x1.00000000000000123456789abcp0L, 0x1.23456789p-1000L, 4.285899851347756186652871946325962330640e-19L, 4.611541215247321502041995872887317363241e-302L); +#endif + END (clog10, complex); } diff --git a/math/s_clog.c b/math/s_clog.c index e28aa5157d..2593066001 100644 --- a/math/s_clog.c +++ b/math/s_clog.c @@ -78,6 +78,13 @@ __clog (__complex__ double x) else __real__ result = __log1p (absy2) / 2.0; } + else if (absx > 1.0 && absx < 2.0 && absy < 1.0 && scale == 0) + { + double d2m1 = (absx - 1.0) * (absx + 1.0); + if (absy >= DBL_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1p (d2m1) / 2.0; + } else { double d = __ieee754_hypot (absx, absy); diff --git a/math/s_clog10.c b/math/s_clog10.c index b733b048b9..ef997ee76c 100644 --- a/math/s_clog10.c +++ b/math/s_clog10.c @@ -81,6 +81,13 @@ __clog10 (__complex__ double x) else __real__ result = __log1p (absy2) * (M_LOG10E / 2.0); } + else if (absx > 1.0 && absx < 2.0 && absy < 1.0 && scale == 0) + { + double d2m1 = (absx - 1.0) * (absx + 1.0); + if (absy >= DBL_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1p (d2m1) * (M_LOG10E / 2.0); + } else { double d = __ieee754_hypot (absx, absy); diff --git a/math/s_clog10f.c b/math/s_clog10f.c index eb1b895aec..c61e8af8ce 100644 --- a/math/s_clog10f.c +++ b/math/s_clog10f.c @@ -83,6 +83,13 @@ __clog10f (__complex__ float x) else __real__ result = __log1pf (absy2) * ((float) M_LOG10E / 2.0f); } + else if (absx > 1.0f && absx < 2.0f && absy < 1.0f && scale == 0) + { + float d2m1 = (absx - 1.0f) * (absx + 1.0f); + if (absy >= FLT_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f); + } else { float d = __ieee754_hypotf (absx, absy); diff --git a/math/s_clog10l.c b/math/s_clog10l.c index 2a380f6f3b..d50f616578 100644 --- a/math/s_clog10l.c +++ b/math/s_clog10l.c @@ -22,6 +22,13 @@ #include #include +/* To avoid spurious underflows, use this definition to treat IBM long + double as approximating an IEEE-style format. */ +#if LDBL_MANT_DIG == 106 +# undef LDBL_EPSILON +# define LDBL_EPSILON 0x1p-106L +#endif + /* log_10 (2). */ #define M_LOG10_2l 0.3010299956639811952137388947244930267682L @@ -75,6 +82,13 @@ __clog10l (__complex__ long double x) else __real__ result = __log1pl (absy2) * (M_LOG10El / 2.0L); } + else if (absx > 1.0L && absx < 2.0L && absy < 1.0L && scale == 0) + { + long double d2m1 = (absx - 1.0L) * (absx + 1.0L); + if (absy >= LDBL_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1pl (d2m1) * (M_LOG10El / 2.0L); + } else { long double d = __ieee754_hypotl (absx, absy); diff --git a/math/s_clogf.c b/math/s_clogf.c index 088730cfd2..92f782c47b 100644 --- a/math/s_clogf.c +++ b/math/s_clogf.c @@ -78,6 +78,13 @@ __clogf (__complex__ float x) else __real__ result = __log1pf (absy2) / 2.0f; } + else if (absx > 1.0f && absx < 2.0f && absy < 1.0f && scale == 0) + { + float d2m1 = (absx - 1.0f) * (absx + 1.0f); + if (absy >= FLT_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1pf (d2m1) / 2.0f; + } else { float d = __ieee754_hypotf (absx, absy); diff --git a/math/s_clogl.c b/math/s_clogl.c index d98a3c02c1..eaba572ce7 100644 --- a/math/s_clogl.c +++ b/math/s_clogl.c @@ -22,6 +22,13 @@ #include #include +/* To avoid spurious underflows, use this definition to treat IBM long + double as approximating an IEEE-style format. */ +#if LDBL_MANT_DIG == 106 +# undef LDBL_EPSILON +# define LDBL_EPSILON 0x1p-106L +#endif + __complex__ long double __clogl (__complex__ long double x) { @@ -71,6 +78,13 @@ __clogl (__complex__ long double x) else __real__ result = __log1pl (absy2) / 2.0L; } + else if (absx > 1.0L && absx < 2.0L && absy < 1.0L && scale == 0) + { + long double d2m1 = (absx - 1.0L) * (absx + 1.0L); + if (absy >= LDBL_EPSILON) + d2m1 += absy * absy; + __real__ result = __log1pl (d2m1) / 2.0L; + } else { long double d = __ieee754_hypotl (absx, absy); -- cgit v1.2.3