dfabf0f021d2caad3f019faf5620e749e83dd425
[dragonfly.git] / lib / msun / src / s_scalbnf.c
1 /* s_scalbnf.c -- float version of s_scalbn.c.
2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3  *
4  * $FreeBSD: src/lib/msun/src/s_scalbnf.c,v 1.5 1999/08/28 00:06:54 peter Exp $
5  * $DragonFly: src/lib/msun/src/Attic/s_scalbnf.c,v 1.2 2003/06/17 04:26:53 dillon Exp $
6  */
7
8 /*
9  * ====================================================
10  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
11  *
12  * Developed at SunPro, a Sun Microsystems, Inc. business.
13  * Permission to use, copy, modify, and distribute this
14  * software is freely granted, provided that this notice
15  * is preserved.
16  * ====================================================
17  */
18
19 #include "math.h"
20 #include "math_private.h"
21
22 #ifdef __STDC__
23 static const float
24 #else
25 static float
26 #endif
27 two25   =  3.355443200e+07,     /* 0x4c000000 */
28 twom25  =  2.9802322388e-08,    /* 0x33000000 */
29 huge   = 1.0e+30,
30 tiny   = 1.0e-30;
31
32 #ifdef __STDC__
33         float scalbnf (float x, int n)
34 #else
35         float scalbn (x,n)
36         float x; int n;
37 #endif
38 {
39         int32_t k,ix;
40         GET_FLOAT_WORD(ix,x);
41         k = (ix&0x7f800000)>>23;                /* extract exponent */
42         if (k==0) {                             /* 0 or subnormal x */
43             if ((ix&0x7fffffff)==0) return x; /* +-0 */
44             x *= two25;
45             GET_FLOAT_WORD(ix,x);
46             k = ((ix&0x7f800000)>>23) - 25;
47             if (n< -50000) return tiny*x;       /*underflow*/
48             }
49         if (k==0xff) return x+x;                /* NaN or Inf */
50         k = k+n;
51         if (k >  0xfe) return huge*copysignf(huge,x); /* overflow  */
52         if (k > 0)                              /* normal result */
53             {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
54         if (k <= -25)
55             if (n > 50000)      /* in case integer overflow in n+k */
56                 return huge*copysignf(huge,x);  /*overflow*/
57             else return tiny*copysignf(tiny,x); /*underflow*/
58         k += 25;                                /* subnormal result */
59         SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
60         return x*twom25;
61 }