Update.
[jlayton/glibc.git] / sysdeps / libm-ieee754 / s_scalblnl.c
1 /* s_scalbnl.c -- long double version of s_scalbn.c.
2  * Conversion to long double by Ulrich Drepper,
3  * Cygnus Support, drepper@cygnus.com.
4  */
5
6 /*
7  * ====================================================
8  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9  *
10  * Developed at SunPro, a Sun Microsystems, Inc. business.
11  * Permission to use, copy, modify, and distribute this
12  * software is freely granted, provided that this notice
13  * is preserved.
14  * ====================================================
15  */
16
17 #if defined(LIBM_SCCS) && !defined(lint)
18 static char rcsid[] = "$NetBSD: $";
19 #endif
20
21 /*
22  * scalbnl (long double x, int n)
23  * scalbnl(x,n) returns x* 2**n  computed by  exponent
24  * manipulation rather than by actually performing an
25  * exponentiation or a multiplication.
26  */
27
28 #include "math.h"
29 #include "math_private.h"
30
31 #ifdef __STDC__
32 static const long double
33 #else
34 static long double
35 #endif
36 two63   =  4.50359962737049600000e+15,
37 twom63  =  1.08420217248550443400e-19,
38 huge   = 1.0e+4900L,
39 tiny   = 1.0e-4900L;
40
41 #ifdef __STDC__
42         long double __scalblnl (long double x, long int n)
43 #else
44         long double __scalblnl (x,n)
45         long double x; long int n;
46 #endif
47 {
48         int32_t k,es,hx,lx;
49         GET_LDOUBLE_WORDS(es,hx,lx,x);
50         k = es&0x7fff;                          /* extract exponent */
51         if (k==0) {                             /* 0 or subnormal x */
52             if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
53             x *= two63;
54             GET_LDOUBLE_EXP(es,x);
55             k = (hx&0x7fff) - 63;
56             }
57         if (k==0x7fff) return x+x;              /* NaN or Inf */
58         k = k+n;
59         if (n> 50000 || k > 0x7ffe)
60           return huge*__copysignl(huge,x); /* overflow  */
61         if (n< -50000)
62           return tiny*__copysignl(tiny,x);
63         if (k > 0)                              /* normal result */
64             {SET_LDOUBLE_EXP(x,(es&0x8000)|k); return x;}
65         if (k <= -63)
66             return tiny*__copysignl(tiny,x);    /*underflow*/
67         k += 54;                                /* subnormal result */
68         SET_LDOUBLE_EXP(x,(es&0x8000)|k);
69         return x*twom63;
70 }
71 weak_alias (__scalblnl, scalblnl)