small cleanup patch for e_pow.c

Bruce Evans brde at
Sun May 10 02:24:06 UTC 2015

On Sat, 9 May 2015, Steve Kargl wrote:

> In reading, e_pow.c I found a small piece of code that
> can be remove.  Anyone object?
> Index: src/e_pow.c
> ===================================================================
> --- src/e_pow.c	(revision 1603)
> +++ src/e_pow.c	(working copy)
> @@ -187,10 +187,6 @@ __ieee754_pow(double x, double y)
>     /* |y| is huge */
> 	if(iy>0x41e00000) { /* if |y| > 2**31 */
> -	    if(iy>0x43f00000){	/* if |y| > 2**64, must o/uflow */
> -		if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
> -		if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
> -	    }
> 	/* over/underflow if x is not close to one */
> 	    if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
> 	    if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;

It seems to be just an optimization.  It is a large optimization for
the huge args, but those are not common, and is at most a tiny
pessimization for non-huge args (just an extra branch which can be
predicted perfectly if non-huge args are never used).

My tests cover huge args uniformly in float space, so they benefit from
optimizations like this more than normal programs.  However, on some
CPUs the exceptions for calculating huge*huge and tiny*tiny when they
overflow/underflow are the main source of slowness, so it doesn't help
much to avoid large code that has to be executed for normal args, unless
the latter would generate multiple exceptions.  Here if you are correct
that the above code can be removed, then the exceptions generated by the
main path can't be too complicated or it would be hard to see that there
are no spurious ones.  We can see this easily for functions like exp(),
and pow() is not very different, because the algorithm is basically
to calculate a small result and then multiply it by 2**k.  The overflows
and underflows only occur in the scaling step.


More information about the freebsd-numerics mailing list