diff options
Diffstat (limited to 'src/math/scalbnf.c')
| -rw-r--r-- | src/math/scalbnf.c | 54 | 
1 files changed, 54 insertions, 0 deletions
diff --git a/src/math/scalbnf.c b/src/math/scalbnf.c new file mode 100644 index 00000000..0a6168b0 --- /dev/null +++ b/src/math/scalbnf.c @@ -0,0 +1,54 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_scalbnf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@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. + * ==================================================== + */ + +#include "libm.h" + +static const float +two25  = 3.355443200e+07,  /* 0x4c000000 */ +twom25 = 2.9802322388e-08, /* 0x33000000 */ +huge   = 1.0e+30, +tiny   = 1.0e-30; + +float scalbnf(float x, int n) +{ +	int32_t k, ix; +	GET_FLOAT_WORD(ix, x); +	k = (ix&0x7f800000)>>23;           /* extract exponent */ +	if (k == 0) {                      /* 0 or subnormal x */ +		if ((ix&0x7fffffff) == 0)  /* +-0 */ +			return x; +		x *= two25; +		GET_FLOAT_WORD(ix, x); +		k = ((ix&0x7f800000)>>23) - 25; +		if (n < -50000) +			return tiny*x;  /*underflow*/ +	} +	if (k == 0xff)                     /* NaN or Inf */ +		return x + x; +	k = k + n; +	if (k > 0xfe) +		return huge*copysignf(huge, x);  /* overflow  */ +	if (k > 0) {                       /* normal result */ +		SET_FLOAT_WORD(x, (ix&0x807fffff)|(k<<23)); +		return x; +	} +	if (k <= -25) +		if (n > 50000)  /* in case integer overflow in n+k */ +			return huge*copysignf(huge,x);  /*overflow*/ +		return tiny*copysignf(tiny, x);  /*underflow*/ +	k += 25;                           /* subnormal result */ +	SET_FLOAT_WORD(x, (ix&0x807fffff)|(k<<23)); +	return x*twom25; +}  | 
