1 /* s_scalblnl.c -- long double version of s_scalbln.c.
2 * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
5 /* @(#)s_scalbln.c 5.1 93/09/24 */
7 * ====================================================
8 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
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
14 * ====================================================
17 #if defined(LIBM_SCCS) && !defined(lint)
18 static char rcsid
[] = "$NetBSD: $";
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.
29 #include "math_private.h"
30 #include <math_ldbl_opt.h>
33 static const long double
37 twolm54
= 5.55111512312578270212e-17, /* 0x3C90000000000000, 0 */
45 two54
= 1.80143985094819840000e+16, /* 0x4350000000000000 */
46 twom54
= 5.55111512312578270212e-17; /* 0x3C90000000000000 */
49 long double __scalblnl (long double x
, long int n
)
51 long double __scalblnl (x
,n
)
52 long double x
; long int n
;
56 union { int64_t i
; double d
; } u
;
57 GET_LDOUBLE_WORDS64(hx
,lx
,x
);
58 k
= (hx
>>52)&0x7ff; /* extract exponent */
60 if (k
==0) { /* 0 or subnormal x */
61 if (((hx
|lx
)&0x7fffffffffffffffULL
)==0) return x
; /* +-0 */
65 k
= ((hx
>>52)&0x7ff) - 54;
67 else if (k
==0x7ff) return x
+x
; /* NaN or Inf */
69 if (n
> 50000 || k
> 0x7fe)
70 return huge
*__copysignl(huge
,x
); /* overflow */
71 if (n
< -50000) return tiny
*__copysignl(tiny
,x
); /*underflow */
72 if (k
> 0) { /* normal result */
73 hx
= (hx
&0x800fffffffffffffULL
)|(k
<<52);
74 if ((lx
& 0x7fffffffffffffffULL
) == 0) { /* low part +-0 */
75 SET_LDOUBLE_WORDS64(x
,hx
,lx
);
78 if (l
== 0) { /* low part subnormal */
82 l
= ((lx
>>52)&0x7ff) - 54;
86 lx
= (lx
&0x800fffffffffffffULL
)|(l
<<52);
88 lx
= (lx
&0x8000000000000000ULL
);
91 u
.i
= (lx
&0x800fffffffffffffULL
)|(l
<<52);
95 SET_LDOUBLE_WORDS64(x
,hx
,lx
);
99 return tiny
*__copysignl(tiny
,x
); /*underflow*/
100 k
+= 54; /* subnormal result */
101 lx
&= 0x8000000000000000ULL
;
102 SET_LDOUBLE_WORDS64(x
,(hx
&0x800fffffffffffffULL
)|(k
<<52),lx
);
105 long_double_symbol (libm
, __scalblnl
, scalblnl
);