aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-08-17 18:30:23 +0930
committerAlan Modra <amodra@gmail.com>2013-10-04 10:35:10 +0930
commitda13146da10360436941e843834c90a9aef5fd7a (patch)
treeb31adbca1c370169d672974f30050ef91444017c
parent603e84104cdc709c8e7dcbac54b9a585bf8dff78 (diff)
downloadglibc-da13146da10360436941e843834c90a9aef5fd7a.tar
glibc-da13146da10360436941e843834c90a9aef5fd7a.tar.gz
glibc-da13146da10360436941e843834c90a9aef5fd7a.tar.bz2
glibc-da13146da10360436941e843834c90a9aef5fd7a.zip
PowerPC floating point little-endian [10 of 15]
http://sourceware.org/ml/libc-alpha/2013-07/msg00201.html These two functions oddly test x+1>0 when a double x is >= 0.0, and similarly when x is negative. I don't see the point of that since the test should always be true. I also don't see any need to convert x+1 to integer rather than simply using xr+1. Note that the standard allows these functions to return any value when the input is outside the range of long long, but it's not too hard to prevent xr+1 overflowing so that's what I've done. (With rounding mode FE_UPWARD, x+1 can be a lot more than what you might naively expect, but perhaps that situation was covered by the x - xrf < 1.0 test.) * sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite. * sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite.
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/powerpc/fpu/s_llround.c33
-rw-r--r--sysdeps/powerpc/fpu/s_llroundf.c33
3 files changed, 37 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 9d2d856729..6bfeb63aaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2013-10-04 Alan Modra <amodra@gmail.com>
+ * sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite.
+ * sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite.
+
+2013-10-04 Alan Modra <amodra@gmail.com>
+
* sysdeps/powerpc/fpu/s_float_bitwise.h (__float_and_test28): Don't
use vector int constants.
(__float_and_test24, __float_and8, __float_get_exp): Likewise.
diff --git a/sysdeps/powerpc/fpu/s_llround.c b/sysdeps/powerpc/fpu/s_llround.c
index 9a01826539..995d0a724a 100644
--- a/sysdeps/powerpc/fpu/s_llround.c
+++ b/sysdeps/powerpc/fpu/s_llround.c
@@ -19,29 +19,28 @@
#include <math.h>
#include <math_ldbl_opt.h>
-/* I think that what this routine is supposed to do is round a value
- to the nearest integer, with values exactly on the boundary rounded
- away from zero. */
-/* This routine relies on (long long)x, when x is out of range of a long long,
- clipping to MAX_LLONG or MIN_LLONG. */
+/* Round to the nearest integer, with values exactly on a 0.5 boundary
+ rounded away from zero, regardless of the current rounding mode.
+ If (long long)x, when x is out of range of a long long, clips at
+ LLONG_MAX or LLONG_MIN, then this implementation also clips. */
long long int
__llround (double x)
{
- double xrf;
- long long int xr;
- xr = (long long int) x;
- xrf = (double) xr;
+ long long xr = (long long) x;
+ double xrf = (double) xr;
+
if (x >= 0.0)
- if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0)
- return x+1;
- else
- return x;
+ {
+ if (x - xrf >= 0.5)
+ xr += (long long) ((unsigned long long) xr + 1) > 0;
+ }
else
- if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0)
- return x-1;
- else
- return x;
+ {
+ if (xrf - x >= 0.5)
+ xr -= (long long) ((unsigned long long) xr - 1) < 0;
+ }
+ return xr;
}
weak_alias (__llround, llround)
#ifdef NO_LONG_DOUBLE
diff --git a/sysdeps/powerpc/fpu/s_llroundf.c b/sysdeps/powerpc/fpu/s_llroundf.c
index 07d12adbfb..0935de6624 100644
--- a/sysdeps/powerpc/fpu/s_llroundf.c
+++ b/sysdeps/powerpc/fpu/s_llroundf.c
@@ -18,28 +18,27 @@
#include <math.h>
-/* I think that what this routine is supposed to do is round a value
- to the nearest integer, with values exactly on the boundary rounded
- away from zero. */
-/* This routine relies on (long long)x, when x is out of range of a long long,
- clipping to MAX_LLONG or MIN_LLONG. */
+/* Round to the nearest integer, with values exactly on a 0.5 boundary
+ rounded away from zero, regardless of the current rounding mode.
+ If (long long)x, when x is out of range of a long long, clips at
+ LLONG_MAX or LLONG_MIN, then this implementation also clips. */
long long int
__llroundf (float x)
{
- float xrf;
- long long int xr;
- xr = (long long int) x;
- xrf = (float) xr;
+ long long xr = (long long) x;
+ float xrf = (float) xr;
+
if (x >= 0.0)
- if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0)
- return x+1;
- else
- return x;
+ {
+ if (x - xrf >= 0.5)
+ xr += (long long) ((unsigned long long) xr + 1) > 0;
+ }
else
- if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0)
- return x-1;
- else
- return x;
+ {
+ if (xrf - x >= 0.5)
+ xr -= (long long) ((unsigned long long) xr - 1) < 0;
+ }
+ return xr;
}
weak_alias (__llroundf, llroundf)