diff options
author | nsz <nsz@port70.net> | 2012-03-18 19:27:39 +0100 |
---|---|---|
committer | nsz <nsz@port70.net> | 2012-03-18 19:27:39 +0100 |
commit | 9b6899f2c5cec70af6cea80ead7ba98fd2366ce9 (patch) | |
tree | b00581953a70005aaed0760cb62cd77bd269df5c /src/math/llrintl.c | |
parent | 9e2a895aaaa4a3985e94ae4f3e24c1af65f9bb34 (diff) | |
download | musl-9b6899f2c5cec70af6cea80ead7ba98fd2366ce9.tar.gz musl-9b6899f2c5cec70af6cea80ead7ba98fd2366ce9.tar.bz2 musl-9b6899f2c5cec70af6cea80ead7ba98fd2366ce9.tar.xz musl-9b6899f2c5cec70af6cea80ead7ba98fd2366ce9.zip |
faster lrint and llrint functions
A faster workaround for spurious inexact exceptions
when the result cannot be represented. The old code
actually could be wrong, because gcc reordered the
integer conversion and the exception check.
Diffstat (limited to 'src/math/llrintl.c')
-rw-r--r-- | src/math/llrintl.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/src/math/llrintl.c b/src/math/llrintl.c index ec2cf86b..f1cc47ed 100644 --- a/src/math/llrintl.c +++ b/src/math/llrintl.c @@ -1,5 +1,7 @@ -#include <math.h> -#include <float.h> +#include <limits.h> +#include <fenv.h> +#include "libm.h" + #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 long long llrintl(long double x) @@ -7,10 +9,22 @@ long long llrintl(long double x) return llrint(x); } #else -#define type long double -#define roundit rintl -#define dtype long long -#define fn llrintl +/* +see comments in lrint.c -#include "lrint.c" +Note that if LLONG_MAX == 0x7fffffffffffffff && LDBL_MANT_DIG == 64 +then x == 2**63 - 0.5 is the only input that overflows and +raises inexact (with tonearest or upward rounding mode) +*/ +long long llrintl(long double x) +{ + int e; + + e = fetestexcept(FE_INEXACT); + x = rintl(x); + if (!e && (x > LLONG_MAX || x < LLONG_MIN)) + feclearexcept(FE_INEXACT); + /* conversion */ + return x; +} #endif |