[BZ #6803] Set errno for scalbln, scalbn
[platform/upstream/glibc.git] / sysdeps / ieee754 / ldbl-128 / s_scalblnl.c
1 /* s_scalblnl.c -- long double version of s_scalbn.c.
2  * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
3  */
4
5 /* @(#)s_scalbn.c 5.1 93/09/24 */
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  * scalblnl (long double x, long int n)
23  * scalblnl(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 static const long double
32 two114 = 2.0769187434139310514121985316880384E+34L, /* 0x4071000000000000, 0 */
33 twom114 = 4.8148248609680896326399448564623183E-35L, /* 0x3F8D000000000000, 0 */
34 huge   = 1.0E+4900L,
35 tiny   = 1.0E-4900L;
36
37 long double __scalblnl (long double x, long int n)
38 {
39         int64_t k,hx,lx;
40         GET_LDOUBLE_WORDS64(hx,lx,x);
41         k = (hx>>48)&0x7fff;            /* extract exponent */
42         if (k==0) {                             /* 0 or subnormal x */
43             if ((lx|(hx&0x7fffffffffffffffULL))==0) return x; /* +-0 */
44             x *= two114;
45             GET_LDOUBLE_MSW64(hx,x);
46             k = ((hx>>48)&0x7fff) - 114;
47         }
48         if (k==0x7fff) return x+x;              /* NaN or Inf */
49         if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow*/
50         if (n> 50000 || k+n > 0x7ffe)
51           return huge*__copysignl(huge,x); /* overflow  */
52         /* Now k and n are bounded we know that k = k+n does not
53            overflow.  */
54         k = k+n;
55         if (k > 0)                              /* normal result */
56             {SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48)); return x;}
57         if (k <= -114)
58           return tiny*__copysignl(tiny,x);      /*underflow*/
59         k += 114;                               /* subnormal result */
60         SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48));
61         return x*twom114;
62 }