提交 79ca8609 编写于 作者: S Szabolcs Nagy 提交者: Rich Felker

fix rint.c and rintf.c when FLT_EVAL_METHOD!=0

The old code used the rounding idiom incorrectly:

  y = (double)(x + 0x1p52) - 0x1p52;

the cast is useless if FLT_EVAL_METHOD==0 and causes a second rounding
if FLT_EVAL_METHOD==2 which can give incorrect result in nearest rounding
mode, so the correct idiom is to add/sub a power-of-2 according to the
characteristics of double_t.

This did not cause actual bug because only i386 is affected where rint
is implemented in asm.

Other rounding functions use a similar idiom, but they give correct
results because they only rely on getting a neighboring integer result
and the rounding direction is fixed up separately independently of the
current rounding mode. However they should be fixed to use the idiom
correctly too.
上级 2da3ab13
#include <float.h>
#include <math.h> #include <math.h>
#include <stdint.h> #include <stdint.h>
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
static const double_t toint = 1/EPS;
double rint(double x) double rint(double x)
{ {
union {double f; uint64_t i;} u = {x}; union {double f; uint64_t i;} u = {x};
...@@ -11,9 +19,9 @@ double rint(double x) ...@@ -11,9 +19,9 @@ double rint(double x)
if (e >= 0x3ff+52) if (e >= 0x3ff+52)
return x; return x;
if (s) if (s)
y = (double)(x - 0x1p52) + 0x1p52; y = x - toint + toint;
else else
y = (double)(x + 0x1p52) - 0x1p52; y = x + toint - toint;
if (y == 0) if (y == 0)
return s ? -0.0 : 0; return s ? -0.0 : 0;
return y; return y;
......
#include <float.h>
#include <math.h> #include <math.h>
#include <stdint.h> #include <stdint.h>
#if FLT_EVAL_METHOD==0
#define EPS FLT_EPSILON
#elif FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
static const float_t toint = 1/EPS;
float rintf(float x) float rintf(float x)
{ {
union {float f; uint32_t i;} u = {x}; union {float f; uint32_t i;} u = {x};
...@@ -11,9 +21,9 @@ float rintf(float x) ...@@ -11,9 +21,9 @@ float rintf(float x)
if (e >= 0x7f+23) if (e >= 0x7f+23)
return x; return x;
if (s) if (s)
y = (float)(x - 0x1p23f) + 0x1p23f; y = x - toint + toint;
else else
y = (float)(x + 0x1p23f) - 0x1p23f; y = x + toint - toint;
if (y == 0) if (y == 0)
return s ? -0.0f : 0.0f; return s ? -0.0f : 0.0f;
return y; return y;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册