summaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/fpu/round_to_integer.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/fpu/round_to_integer.h')
-rw-r--r--sysdeps/powerpc/fpu/round_to_integer.h20
1 files changed, 19 insertions, 1 deletions
diff --git a/sysdeps/powerpc/fpu/round_to_integer.h b/sysdeps/powerpc/fpu/round_to_integer.h
index ff77dde394..b318e37190 100644
--- a/sysdeps/powerpc/fpu/round_to_integer.h
+++ b/sysdeps/powerpc/fpu/round_to_integer.h
@@ -24,7 +24,8 @@
enum round_mode
{
CEIL,
- FLOOR
+ FLOOR,
+ ROUND
};
static inline void
@@ -35,6 +36,7 @@ set_fenv_mode (enum round_mode mode)
{
case CEIL: rmode = FE_UPWARD; break;
case FLOOR: rmode = FE_DOWNWARD; break;
+ case ROUND: rmode = FE_TOWARDZERO; break;
default: rmode = FE_TONEAREST; break;
}
__fesetround_inline_nocheck (rmode);
@@ -57,12 +59,24 @@ round_to_integer_float (enum round_mode mode, float x)
set_fenv_mode (mode);
if (x > 0.0)
{
+ /* IEEE 1003.1 round function. IEEE specifies "round to the nearest
+ integer value, rounding halfway cases away from zero, regardless of
+ the current rounding mode." However PowerPC Architecture defines
+ "Round to Nearest" as "Choose the best approximation. In case of a
+ tie, choose the one that is even (least significant bit o).".
+ So we can't use the PowerPC "Round to Nearest" mode. Instead we set
+ "Round toward Zero" mode and round by adding +-0.5 before rounding
+ to the integer value. */
+ if (mode == ROUND)
+ r += 0.5f;
r += 0x1p+23;
r -= 0x1p+23;
r = fabs (r);
}
else if (x < 0.0)
{
+ if (mode == ROUND)
+ r -= 0.5f;
r -= 0x1p+23;
r += 0x1p+23;
r = -fabs (r);
@@ -89,12 +103,16 @@ round_to_integer_double (enum round_mode mode, double x)
set_fenv_mode (mode);
if (x > 0.0)
{
+ if (mode == ROUND)
+ r += 0.5;
r += 0x1p+52;
r -= 0x1p+52;
r = fabs (r);
}
else if (x < 0.0)
{
+ if (mode == ROUND)
+ r -= 0.5;
r -= 0x1p+52;
r += 0x1p+52;
r = -fabs (r);