libm: Sync with FreeBSD (gains 6 long double functions)
[dragonfly.git] / lib / libm / 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
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  * $FreeBSD: head/lib/msun/src/s_scalbnf.c 143205 2005-03-07 04:52:43Z das $
16  */
17
18
19 #include "math.h"
20 #include "math_private.h"
21
22 static const float
23 two25   =  3.355443200e+07,     /* 0x4c000000 */
24 twom25  =  2.9802322388e-08,    /* 0x33000000 */
25 huge   = 1.0e+30,
26 tiny   = 1.0e-30;
27
28 float
29 scalbnf (float x, int n)
30 {
31         int32_t k,ix;
32         GET_FLOAT_WORD(ix,x);
33         k = (ix&0x7f800000)>>23;                /* extract exponent */
34         if (k==0) {                             /* 0 or subnormal x */
35             if ((ix&0x7fffffff)==0) return x; /* +-0 */
36             x *= two25;
37             GET_FLOAT_WORD(ix,x);
38             k = ((ix&0x7f800000)>>23) - 25;
39             if (n< -50000) return tiny*x;       /*underflow*/
40             }
41         if (k==0xff) return x+x;                /* NaN or Inf */
42         k = k+n;
43         if (k >  0xfe) return huge*copysignf(huge,x); /* overflow  */
44         if (k > 0)                              /* normal result */
45             {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
46         if (k <= -25)
47             if (n > 50000)      /* in case integer overflow in n+k */
48                 return huge*copysignf(huge,x);  /*overflow*/
49             else return tiny*copysignf(tiny,x); /*underflow*/
50         k += 25;                                /* subnormal result */
51         SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
52         return x*twom25;
53 }
54
55 __strong_reference(scalbnf, ldexpf);