Home | History | Annotate | Download | only in libm
      1 /* sf_scalbn.c -- float version of s_scalbn.c.
      2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian (at) cygnus.com.
      3  */
      4 
      5 /*
      6  * ====================================================
      7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      8  *
      9  * Developed at SunPro, a Sun Microsystems, Inc. business.
     10  * Permission to use, copy, modify, and distribute this
     11  * software is freely granted, provided that this notice
     12  * is preserved.
     13  * ====================================================
     14  */
     15 
     16 #include "fdlibm.h"
     17 #include <limits.h>
     18 #include <float.h>
     19 
     20 #if INT_MAX > 50000
     21 #define OVERFLOW_INT 50000
     22 #else
     23 #define OVERFLOW_INT 30000
     24 #endif
     25 
     26 #ifdef __STDC__
     27 static const float
     28 #else
     29 static float
     30 #endif
     31 two25   =  3.355443200e+07,	/* 0x4c000000 */
     32 twom25  =  2.9802322388e-08,	/* 0x33000000 */
     33 huge   = 1.0e+30,
     34 tiny   = 1.0e-30;
     35 
     36 #ifdef __STDC__
     37 	float scalbnf (float x, int n)
     38 #else
     39 	float scalbnf (x,n)
     40 	float x; int n;
     41 #endif
     42 {
     43 	__int32_t  k,ix;
     44 	__uint32_t hx;
     45 
     46 	GET_FLOAT_WORD(ix,x);
     47 	hx = ix&0x7fffffff;
     48         k = hx>>23;		/* extract exponent */
     49 	if (FLT_UWORD_IS_ZERO(hx))
     50 	    return x;
     51         if (!FLT_UWORD_IS_FINITE(hx))
     52 	    return x+x;		/* NaN or Inf */
     53         if (FLT_UWORD_IS_SUBNORMAL(hx)) {
     54 	    x *= two25;
     55 	    GET_FLOAT_WORD(ix,x);
     56 	    k = ((ix&0x7f800000)>>23) - 25;
     57             if (n< -50000) return tiny*x; 	/*underflow*/
     58         }
     59         k = k+n;
     60         if (k > FLT_LARGEST_EXP) return huge*copysignf(huge,x); /* overflow  */
     61         if (k > 0) 				/* normal result */
     62 	    {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
     63         if (k < FLT_SMALLEST_EXP) {
     64             if (n > OVERFLOW_INT) 	/* in case integer overflow in n+k */
     65 		return huge*copysignf(huge,x);	/*overflow*/
     66 	    else return tiny*copysignf(tiny,x);	/*underflow*/
     67         }
     68         k += 25;				/* subnormal result */
     69 	SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
     70         return x*twom25;
     71 }
     72 
     73 #ifdef _DOUBLE_IS_32BITS
     74 
     75 #ifdef __STDC__
     76 	double scalbn(double x, int n)
     77 #else
     78 	double scalbn(x,n)
     79 	double x;
     80 	int n;
     81 #endif
     82 {
     83 	return (double) scalbnf((float) x, n);
     84 }
     85 
     86 #endif /* defined(_DOUBLE_IS_32BITS) */
     87