Fix ctan, ctanh of subnormals in round-upwards mode (bug 14328)
Andreas Jaeger
aj@suse.com
Wed Jul 4 06:04:00 GMT 2012
On 07/03/2012 11:32 PM, Joseph S. Myers wrote:
> Bug 14328 is inaccuracy from ctan and ctanh on certain cases of
> subnormal inputs, in round-upwards mode only.
>
> Consider the following code from ctan:
>
> double sinhix = __ieee754_sinh (__imag__ x);
> double coshix = __ieee754_cosh (__imag__ x);
>
> den = cosrx * cosrx + sinhix * sinhix;
> __real__ res = sinrx * cosrx / den;
> __imag__ res = sinhix * coshix / den;
>
> If __imag__ x is subnormal, sinh (__imag__ x) is very close to x (but
> slightly bigger) and cosh (__imag__ x) is very close to 1 (but
> slightly bigger). In fact, sinh does not honour the rounding mode for
> subnormal inputs (it just returns the input), but cosh does honour the
> rounding mode in this case (and returns a value 1ulp above 1). sinhix
> * coshix is then (rounded upwards) a subnormal value 1ulp above x. If
> cosrx is close to 0 (__real__ x close to an odd multiple of pi/2),
> then the scaling up on division by den magnifies the 1ulp error on the
> subnormal sinhix * coshix to a much larger error in the final
> imaginary part of the result.
>
> This patch fixes this issue by using x and 1 instead of calling sinh
> and cosh, for fabs (__imag__ x) <= DBL_MIN. To avoid spurious
> underflow exceptions, the multiplication sinhix * sinhix must also be
> avoided if that would underflow. The condition fabs (sinhix) > fabs
> (cosrx) * DBL_EPSILON is used for when to perform the multiplication;
> if false, the multiplication certainly isn't needed[*], while if true,
> the multiplication won't result in underflow (cos values of
> floating-point numbers never get that close to 0).
>
> Tested x86_64 and x86 and ulps updated accordingly.
>
> The same issue applies in principle to calls to sincos in various
> complex functions (cexp ccos ccosh csin csinh ctan ctanh), with a
> similar fix (use x and 1 for tiny x rather than calling sincos). But
> it looks like none of the current sincos implementations honour the
> rounding mode for subnormal inputs, so I think the issue is latent
> there; I propose to address it (making the functions more robust) in
> separate patches.
>
> [*] Actually, sqrt (DBL_EPSILON) would be more like the right thing
> here. But there's no macro for that and I'd rather not rely on it
> being constant folded; I don't think GCC will constant-fold much at
> all for ldbl128-ibm.
>
> 2012-07-03 Joseph Myers <joseph@codesourcery.com>
>
> [BZ #14328]
> * math/s_ctan.c (__ctan): Do not call sinh and cosh for subnormals
> or multiply small sinh result by itself.
> * math/s_ctanf.c (__ctanf): Likewise.
> * math/s_ctanh.c (__ctanh): Likewise.
> * math/s_ctanhf.c (__ctanhf): Likewise.
> * math/s_ctanhl.c (__ctanhl): Likewise.
> * math/s_ctanl.c (__ctanl): Likewise.
> * math/libm-test.inc (ctan_test_tonearest): New function.
> (ctan_test_towardzero): Likewise.
> (ctan_test_downward): Likewise.
> (ctan_test_upward): Likewise.
> (ctanh_test_tonearest): Likewise.
> (ctanh_test_towardzero): Likewise.
> (ctanh_test_downward): Likewise.
> (ctanh_test_upward): Likewise.
> (main): Call these new functions.
> * sysdeps/i386/fpu/libm-test-ulps: Update.
> * sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
Thanks ,this is fine,
Andreas
--
Andreas Jaeger aj@{suse.com,opensuse.org} Twitter/Identica: jaegerandi
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn,Jennifer Guild,Felix Imendörffer,HRB16746 (AG Nürnberg)
GPG fingerprint = 93A3 365E CE47 B889 DF7F FED1 389A 563C C272 A126
More information about the Libc-alpha
mailing list