mirror of git://gcc.gnu.org/git/gcc.git
c99_functions.c (nextafterf): New implementation that works correctly with denormalized numbers.
* intrinsics/c99_functions.c (nextafterf): New implementation that works correctly with denormalized numbers. From-SVN: r85724
This commit is contained in:
parent
9d8646d7b0
commit
067a5735c5
|
@ -1,4 +1,10 @@
|
||||||
2004-09-09 Victor Leikehman <lei@il.ibm.com>
|
2004-08-09 Richard Henderson <rth@redhat.com>
|
||||||
|
Roger Sayle <roger@eyesopen.com>
|
||||||
|
|
||||||
|
* intrinsics/c99_functions.c (nextafterf): New implementation that
|
||||||
|
works correctly with denormalized numbers.
|
||||||
|
|
||||||
|
2004-08-09 Victor Leikehman <lei@il.ibm.com>
|
||||||
|
|
||||||
* m4/matmul.m4, m4/matmull.m4, intrinsics/eoshift0.c,
|
* m4/matmul.m4, m4/matmull.m4, intrinsics/eoshift0.c,
|
||||||
intrinsics/eoshift2.c, intrinsics/transpose_generic.c:
|
intrinsics/eoshift2.c, intrinsics/transpose_generic.c:
|
||||||
|
|
|
@ -188,61 +188,60 @@ tanhf(float x)
|
||||||
#ifndef HAVE_NEXTAFTERF
|
#ifndef HAVE_NEXTAFTERF
|
||||||
/* This is a portable implementation of nextafterf that is intended to be
|
/* This is a portable implementation of nextafterf that is intended to be
|
||||||
independent of the floating point format or its in memory representation.
|
independent of the floating point format or its in memory representation.
|
||||||
This implementation skips denormalized values, for example returning
|
This implementation works correctly with denormalized values. */
|
||||||
FLT_MIN as the next value after zero, as many target's frexpf, scalbnf
|
|
||||||
and ldexpf functions don't work as expected with denormalized values. */
|
|
||||||
float
|
float
|
||||||
nextafterf(float x, float y)
|
nextafterf(float x, float y)
|
||||||
{
|
{
|
||||||
int origexp, newexp;
|
/* This variable is marked volatile to avoid excess precision problems
|
||||||
|
on some platforms, including IA-32. */
|
||||||
|
volatile float delta;
|
||||||
|
float absx, denorm_min;
|
||||||
|
|
||||||
if (isnan(x) || isnan(y))
|
if (isnan(x) || isnan(y))
|
||||||
return x+y;
|
return x + y;
|
||||||
if (x == y)
|
if (x == y)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
if (x == 0.0f)
|
/* absx = fabsf (x); */
|
||||||
return y > 0.0f ? FLT_MIN : -FLT_MIN;
|
absx = (x < 0.0) ? -x : x;
|
||||||
|
|
||||||
frexpf(x, &origexp);
|
/* __FLT_DENORM_MIN__ is non-zero iff the target supports denormals. */
|
||||||
if (x >= 0.0)
|
if (__FLT_DENORM_MIN__ == 0.0f)
|
||||||
{
|
denorm_min = __FLT_MIN__;
|
||||||
if (y > x)
|
else
|
||||||
{
|
denorm_min = __FLT_DENORM_MIN__;
|
||||||
if (x < FLT_MIN)
|
|
||||||
return FLT_MIN;
|
if (absx < __FLT_MIN__)
|
||||||
return x + scalbnf(FLT_EPSILON, origexp-1);
|
delta = denorm_min;
|
||||||
}
|
|
||||||
else if (x > FLT_MIN)
|
|
||||||
{
|
|
||||||
float temp = x - scalbnf(FLT_EPSILON, origexp-1);
|
|
||||||
frexpf(temp, &newexp);
|
|
||||||
if (newexp == origexp)
|
|
||||||
return temp;
|
|
||||||
return x - scalbnf(FLT_EPSILON, origexp-2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (y < x)
|
float frac;
|
||||||
{
|
int exp;
|
||||||
if (x > -FLT_MIN)
|
|
||||||
return -FLT_MIN;
|
/* Discard the fraction from x. */
|
||||||
return x - scalbnf(FLT_EPSILON, origexp-1);
|
frac = frexpf (absx, &exp);
|
||||||
}
|
delta = scalbnf (0.5f, exp);
|
||||||
else if (x < -FLT_MIN)
|
|
||||||
{
|
/* Scale x by the epsilon of the representation. By rights we should
|
||||||
float temp = x + scalbnf(FLT_EPSILON, origexp-1);
|
have been able to combine this with scalbnf, but some targets don't
|
||||||
frexpf(temp, &newexp);
|
get that correct with denormals. */
|
||||||
if (newexp == origexp)
|
delta *= __FLT_EPSILON__;
|
||||||
return temp;
|
|
||||||
return x + scalbnf(FLT_EPSILON, origexp-2);
|
/* If we're going to be reducing the absolute value of X, and doing so
|
||||||
}
|
would reduce the exponent of X, then the delta to be applied is
|
||||||
else
|
one exponent smaller. */
|
||||||
return 0.0f;
|
if (frac == 0.5f && (y < x) == (x > 0))
|
||||||
|
delta *= 0.5f;
|
||||||
|
|
||||||
|
/* If that underflows to zero, then we're back to the minimum. */
|
||||||
|
if (delta == 0.0f)
|
||||||
|
delta = denorm_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (y < x)
|
||||||
|
delta = -delta;
|
||||||
|
|
||||||
|
return x + delta;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue