glibc/sysdeps/i386/fpu/s_nexttoward.c
Joseph Myers 54142c44e9 Use math_narrow_eval more consistently.
Where glibc code needs to avoid excess range and precision in
floating-point arithmetic, code variously uses either asms or volatile
to force the results of that arithmetic to memory; mostly this is
conditional on FLT_EVAL_METHOD, but in the case of lrint / llrint
functions some use of volatile is unconditional (and is present
unnecessarily in versions for long double).  This patch make such code
use the recently-added math_narrow_eval macro consistently, removing
the unnecessary uses of volatile in long double lrint / llrint
implementations completely.

Tested for x86_64, x86, mips64 and powerpc.

	* math/s_nexttowardf.c (__nexttowardf): Use math_narrow_eval.
	* stdlib/strtod_l.c: Include <math_private.h>.
	(overflow_value): Use math_narrow_eval.
	(underflow_value): Likewise.
	* sysdeps/i386/fpu/s_nexttoward.c (__nexttoward): Likewise.
	* sysdeps/i386/fpu/s_nexttowardf.c (__nexttowardf): Likewise.
	* sysdeps/ieee754/dbl-64/e_gamma_r.c (gamma_positive): Likewise.
	(__ieee754_gamma_r): Likewise.
	* sysdeps/ieee754/dbl-64/gamma_productf.c (__gamma_productf):
	Likewise.
	* sysdeps/ieee754/dbl-64/k_rem_pio2.c (__kernel_rem_pio2):
	Likewise.
	* sysdeps/ieee754/dbl-64/lgamma_neg.c (__lgamma_neg): Likewise.
	* sysdeps/ieee754/dbl-64/s_erf.c (__erfc): Likewise.
	* sysdeps/ieee754/dbl-64/s_llrint.c (__llrint): Likewise.
	* sysdeps/ieee754/dbl-64/s_lrint.c (__lrint): Likewise.
	* sysdeps/ieee754/flt-32/e_gammaf_r.c (gammaf_positive): Likewise.
	(__ieee754_gammaf_r): Likewise.
	* sysdeps/ieee754/flt-32/k_rem_pio2f.c (__kernel_rem_pio2f):
	Likewise.
	* sysdeps/ieee754/flt-32/lgamma_negf.c (__lgamma_negf): Likewise.
	* sysdeps/ieee754/flt-32/s_erff.c (__erfcf): Likewise.
	* sysdeps/ieee754/flt-32/s_llrintf.c (__llrintf): Likewise.
	* sysdeps/ieee754/flt-32/s_lrintf.c (__lrintf): Likewise.
	* sysdeps/ieee754/ldbl-128/s_llrintl.c (__llrintl): Do not use
	volatile.
	* sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl): Likewise.
	* sysdeps/ieee754/ldbl-128/s_nexttoward.c (__nexttoward): Use
	math_narrow_eval.
	* sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward):
	Likewise.
	* sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf):
	Likewise.
	* sysdeps/ieee754/ldbl-96/gamma_product.c (__gamma_product):
	Likewise.
	* sysdeps/ieee754/ldbl-96/s_llrintl.c (__llrintl): Do not use
	volatile.
	* sysdeps/ieee754/ldbl-96/s_lrintl.c (__lrintl): Likewise.
	* sysdeps/ieee754/ldbl-96/s_nexttoward.c (__nexttoward): Use
	math_narrow_eval.
	* sysdeps/ieee754/ldbl-96/s_nexttowardf.c (__nexttowardf):
	Likewise.
	* sysdeps/ieee754/ldbl-opt/s_nexttowardfd.c (__nldbl_nexttowardf):
	Likewise.
2015-09-23 18:14:57 +00:00

91 lines
2.3 KiB
C

/* s_nexttoward.c
* Special i387 version
* Conversion from s_nextafter.c by Ulrich Drepper, Cygnus Support,
* drepper@cygnus.com.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: $";
#endif
/* IEEE functions
* nexttoward(x,y)
* return the next machine floating-point number of x in the
* direction toward y.
* Special cases:
*/
#include <math.h>
#include <math_private.h>
#include <float.h>
double __nexttoward(double x, long double y)
{
int32_t hx,ix,iy;
u_int32_t lx,hy,ly,esy;
EXTRACT_WORDS(hx,lx,x);
GET_LDOUBLE_WORDS(esy,hy,ly,y);
ix = hx&0x7fffffff; /* |x| */
iy = esy&0x7fff; /* |y| */
/* Intel's extended format has the normally implicit 1 explicit
present. Sigh! */
if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */
return x+y;
if((long double) x==y) return y; /* x=y, return y */
if((ix|lx)==0) { /* x == 0 */
double u;
INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */
u = math_opt_barrier (x);
u = u * u;
math_force_eval (u); /* raise underflow flag */
return x;
}
if(hx>=0) { /* x > 0 */
if (x > y) { /* x -= ulp */
if(lx==0) hx -= 1;
lx -= 1;
} else { /* x < y, x += ulp */
lx += 1;
if(lx==0) hx += 1;
}
} else { /* x < 0 */
if (x < y) { /* x -= ulp */
if(lx==0) hx -= 1;
lx -= 1;
} else { /* x > y, x += ulp */
lx += 1;
if(lx==0) hx += 1;
}
}
hy = hx&0x7ff00000;
if(hy>=0x7ff00000) {
x = math_narrow_eval (x+x); /* overflow */
return x;
}
if(hy<0x00100000) {
double u = x*x; /* underflow */
math_force_eval (u); /* raise underflow flag */
}
INSERT_WORDS(x,hx,lx);
return x;
}
weak_alias (__nexttoward, nexttoward)
#ifdef NO_LONG_DOUBLE
strong_alias (__nexttoward, __nexttowardl)
weak_alias (__nexttoward, nexttowardl)
#endif